@tanstack/devtools-vite 0.3.8 → 0.3.9

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.
@@ -1 +1,4 @@
1
- export declare function addSourceToJsx(code: string, id: string): import('@babel/generator').GeneratorResult | undefined;
1
+ export declare function addSourceToJsx(code: string, id: string, ignore?: {
2
+ files?: Array<string | RegExp>;
3
+ components?: Array<string | RegExp>;
4
+ }): import('@babel/generator').GeneratorResult | undefined;
@@ -1,5 +1,6 @@
1
1
  import { normalizePath } from "vite";
2
2
  import { gen, trav } from "./babel.js";
3
+ import { matcher } from "./matcher.js";
3
4
  import { parse } from "@babel/parser";
4
5
  import * as t from "@babel/types";
5
6
  const getPropsNameFromFunctionDeclaration = (functionDeclaration) => {
@@ -70,13 +71,14 @@ const getNameOfElement = (element) => {
70
71
  }
71
72
  return `${element.namespace.name}:${element.name.name}`;
72
73
  };
73
- const transformJSX = (element, propsName, file) => {
74
+ const transformJSX = (element, propsName, file, ignorePatterns) => {
74
75
  const loc = element.node.loc;
75
76
  if (!loc) return;
76
77
  const line = loc.start.line;
77
78
  const column = loc.start.column;
78
79
  const nameOfElement = getNameOfElement(element.node.name);
79
- if (nameOfElement === "Fragment" || nameOfElement === "React.Fragment") {
80
+ const isIgnored = matcher(ignorePatterns, nameOfElement);
81
+ if (nameOfElement === "Fragment" || nameOfElement === "React.Fragment" || isIgnored) {
80
82
  return;
81
83
  }
82
84
  const hasDataSource = element.node.attributes.some(
@@ -96,7 +98,7 @@ const transformJSX = (element, propsName, file) => {
96
98
  );
97
99
  return true;
98
100
  };
99
- const transform = (ast, file) => {
101
+ const transform = (ast, file, ignorePatterns) => {
100
102
  let didTransform = false;
101
103
  trav(ast, {
102
104
  FunctionDeclaration(functionDeclaration) {
@@ -105,7 +107,12 @@ const transform = (ast, file) => {
105
107
  );
106
108
  functionDeclaration.traverse({
107
109
  JSXOpeningElement(element) {
108
- const transformed = transformJSX(element, propsName, file);
110
+ const transformed = transformJSX(
111
+ element,
112
+ propsName,
113
+ file,
114
+ ignorePatterns
115
+ );
109
116
  if (transformed) {
110
117
  didTransform = true;
111
118
  }
@@ -116,7 +123,12 @@ const transform = (ast, file) => {
116
123
  const propsName = getPropsNameFromFunctionDeclaration(path.node);
117
124
  path.traverse({
118
125
  JSXOpeningElement(element) {
119
- const transformed = transformJSX(element, propsName, file);
126
+ const transformed = transformJSX(
127
+ element,
128
+ propsName,
129
+ file,
130
+ ignorePatterns
131
+ );
120
132
  if (transformed) {
121
133
  didTransform = true;
122
134
  }
@@ -127,7 +139,12 @@ const transform = (ast, file) => {
127
139
  const propsName = getPropsNameFromFunctionDeclaration(path.node);
128
140
  path.traverse({
129
141
  JSXOpeningElement(element) {
130
- const transformed = transformJSX(element, propsName, file);
142
+ const transformed = transformJSX(
143
+ element,
144
+ propsName,
145
+ file,
146
+ ignorePatterns
147
+ );
131
148
  if (transformed) {
132
149
  didTransform = true;
133
150
  }
@@ -144,7 +161,12 @@ const transform = (ast, file) => {
144
161
  const propsName = getPropsNameFromFunctionDeclaration(functionDeclaration);
145
162
  path.traverse({
146
163
  JSXOpeningElement(element) {
147
- const transformed = transformJSX(element, propsName, file);
164
+ const transformed = transformJSX(
165
+ element,
166
+ propsName,
167
+ file,
168
+ ignorePatterns
169
+ );
148
170
  if (transformed) {
149
171
  didTransform = true;
150
172
  }
@@ -154,15 +176,19 @@ const transform = (ast, file) => {
154
176
  });
155
177
  return didTransform;
156
178
  };
157
- function addSourceToJsx(code, id) {
179
+ function addSourceToJsx(code, id, ignore = {}) {
158
180
  const [filePath] = id.split("?");
159
181
  const location = filePath?.replace(normalizePath(process.cwd()), "");
182
+ const fileIgnored = matcher(ignore.files || [], location);
183
+ if (fileIgnored) {
184
+ return;
185
+ }
160
186
  try {
161
187
  const ast = parse(code, {
162
188
  sourceType: "module",
163
189
  plugins: ["jsx", "typescript"]
164
190
  });
165
- const didTransform = transform(ast, location);
191
+ const didTransform = transform(ast, location, ignore.components || []);
166
192
  if (!didTransform) {
167
193
  return;
168
194
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inject-source.js","sources":["../../src/inject-source.ts"],"sourcesContent":["import { normalizePath } from 'vite'\nimport { gen, parse, t, trav } from './babel'\nimport type { types as Babel, NodePath } from '@babel/core'\nimport type { ParseResult } from '@babel/parser'\n\nconst getPropsNameFromFunctionDeclaration = (\n functionDeclaration:\n | t.VariableDeclarator\n | t.FunctionExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression,\n) => {\n let propsName: string | null = null\n\n if (functionDeclaration.type === 'FunctionExpression') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n if (functionDeclaration.type === 'ArrowFunctionExpression') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n if (functionDeclaration.type === 'FunctionDeclaration') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n // Arrow function case\n if (\n functionDeclaration.init?.type === 'ArrowFunctionExpression' ||\n functionDeclaration.init?.type === 'FunctionExpression'\n ) {\n const firstArgument = functionDeclaration.init.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n }\n return propsName\n}\n\nconst getNameOfElement = (\n element: t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName,\n): string => {\n if (element.type === 'JSXIdentifier') {\n return element.name\n }\n if (element.type === 'JSXMemberExpression') {\n return `${getNameOfElement(element.object)}.${getNameOfElement(element.property)}`\n }\n\n return `${element.namespace.name}:${element.name.name}`\n}\n\nconst transformJSX = (\n element: NodePath<t.JSXOpeningElement>,\n propsName: string | null,\n file: string,\n) => {\n const loc = element.node.loc\n if (!loc) return\n const line = loc.start.line\n const column = loc.start.column\n const nameOfElement = getNameOfElement(element.node.name)\n\n if (nameOfElement === 'Fragment' || nameOfElement === 'React.Fragment') {\n return\n }\n const hasDataSource = element.node.attributes.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === 'data-tsd-source',\n )\n // Check if props are spread\n const hasSpread = element.node.attributes.some(\n (attr) =>\n attr.type === 'JSXSpreadAttribute' &&\n attr.argument.type === 'Identifier' &&\n attr.argument.name === propsName,\n )\n\n if (hasSpread || hasDataSource) {\n // Do not inject if props are spread\n return\n }\n\n // Inject data-source as a string: \"<file>:<line>:<column>\"\n element.node.attributes.push(\n t.jsxAttribute(\n t.jsxIdentifier('data-tsd-source'),\n t.stringLiteral(`${file}:${line}:${column + 1}`),\n ),\n )\n\n return true\n}\n\nconst transform = (ast: ParseResult<Babel.File>, file: string) => {\n let didTransform = false\n\n trav(ast, {\n FunctionDeclaration(functionDeclaration) {\n const propsName = getPropsNameFromFunctionDeclaration(\n functionDeclaration.node,\n )\n functionDeclaration.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(element, propsName, file)\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n ArrowFunctionExpression(path) {\n const propsName = getPropsNameFromFunctionDeclaration(path.node)\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(element, propsName, file)\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n FunctionExpression(path) {\n const propsName = getPropsNameFromFunctionDeclaration(path.node)\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(element, propsName, file)\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n VariableDeclaration(path) {\n const functionDeclaration = path.node.declarations.find((decl) => {\n return (\n decl.init?.type === 'ArrowFunctionExpression' ||\n decl.init?.type === 'FunctionExpression'\n )\n })\n if (!functionDeclaration) {\n return\n }\n const propsName = getPropsNameFromFunctionDeclaration(functionDeclaration)\n\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(element, propsName, file)\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n })\n\n return didTransform\n}\n\nexport function addSourceToJsx(code: string, id: string) {\n const [filePath] = id.split('?')\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n const location = filePath?.replace(normalizePath(process.cwd()), '')!\n\n try {\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n })\n const didTransform = transform(ast, location)\n if (!didTransform) {\n return\n }\n return gen(ast, {\n sourceMaps: true,\n retainLines: true,\n filename: id,\n sourceFileName: filePath,\n })\n } catch (e) {\n return\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inject-source.js","sources":["../../src/inject-source.ts"],"sourcesContent":["import { normalizePath } from 'vite'\nimport { gen, parse, t, trav } from './babel'\nimport { matcher } from './matcher'\nimport type { types as Babel, NodePath } from '@babel/core'\nimport type { ParseResult } from '@babel/parser'\n\nconst getPropsNameFromFunctionDeclaration = (\n functionDeclaration:\n | t.VariableDeclarator\n | t.FunctionExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression,\n) => {\n let propsName: string | null = null\n\n if (functionDeclaration.type === 'FunctionExpression') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n if (functionDeclaration.type === 'ArrowFunctionExpression') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n if (functionDeclaration.type === 'FunctionDeclaration') {\n const firstArgument = functionDeclaration.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n return propsName\n }\n // Arrow function case\n if (\n functionDeclaration.init?.type === 'ArrowFunctionExpression' ||\n functionDeclaration.init?.type === 'FunctionExpression'\n ) {\n const firstArgument = functionDeclaration.init.params[0]\n // handles (props) => {}\n if (firstArgument && firstArgument.type === 'Identifier') {\n propsName = firstArgument.name\n }\n // handles ({ ...props }) => {}\n if (firstArgument && firstArgument.type === 'ObjectPattern') {\n firstArgument.properties.forEach((prop) => {\n if (\n prop.type === 'RestElement' &&\n prop.argument.type === 'Identifier'\n ) {\n propsName = prop.argument.name\n }\n })\n }\n }\n return propsName\n}\n\nconst getNameOfElement = (\n element: t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName,\n): string => {\n if (element.type === 'JSXIdentifier') {\n return element.name\n }\n if (element.type === 'JSXMemberExpression') {\n return `${getNameOfElement(element.object)}.${getNameOfElement(element.property)}`\n }\n\n return `${element.namespace.name}:${element.name.name}`\n}\n\nconst transformJSX = (\n element: NodePath<t.JSXOpeningElement>,\n propsName: string | null,\n file: string,\n ignorePatterns: Array<string | RegExp>,\n) => {\n const loc = element.node.loc\n if (!loc) return\n const line = loc.start.line\n const column = loc.start.column\n const nameOfElement = getNameOfElement(element.node.name)\n const isIgnored = matcher(ignorePatterns, nameOfElement)\n if (\n nameOfElement === 'Fragment' ||\n nameOfElement === 'React.Fragment' ||\n isIgnored\n ) {\n return\n }\n const hasDataSource = element.node.attributes.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === 'data-tsd-source',\n )\n // Check if props are spread\n const hasSpread = element.node.attributes.some(\n (attr) =>\n attr.type === 'JSXSpreadAttribute' &&\n attr.argument.type === 'Identifier' &&\n attr.argument.name === propsName,\n )\n\n if (hasSpread || hasDataSource) {\n // Do not inject if props are spread\n return\n }\n\n // Inject data-source as a string: \"<file>:<line>:<column>\"\n element.node.attributes.push(\n t.jsxAttribute(\n t.jsxIdentifier('data-tsd-source'),\n t.stringLiteral(`${file}:${line}:${column + 1}`),\n ),\n )\n\n return true\n}\n\nconst transform = (\n ast: ParseResult<Babel.File>,\n file: string,\n ignorePatterns: Array<string | RegExp>,\n) => {\n let didTransform = false\n\n trav(ast, {\n FunctionDeclaration(functionDeclaration) {\n const propsName = getPropsNameFromFunctionDeclaration(\n functionDeclaration.node,\n )\n functionDeclaration.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(\n element,\n propsName,\n file,\n ignorePatterns,\n )\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n ArrowFunctionExpression(path) {\n const propsName = getPropsNameFromFunctionDeclaration(path.node)\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(\n element,\n propsName,\n file,\n ignorePatterns,\n )\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n FunctionExpression(path) {\n const propsName = getPropsNameFromFunctionDeclaration(path.node)\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(\n element,\n propsName,\n file,\n ignorePatterns,\n )\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n VariableDeclaration(path) {\n const functionDeclaration = path.node.declarations.find((decl) => {\n return (\n decl.init?.type === 'ArrowFunctionExpression' ||\n decl.init?.type === 'FunctionExpression'\n )\n })\n if (!functionDeclaration) {\n return\n }\n const propsName = getPropsNameFromFunctionDeclaration(functionDeclaration)\n\n path.traverse({\n JSXOpeningElement(element) {\n const transformed = transformJSX(\n element,\n propsName,\n file,\n ignorePatterns,\n )\n if (transformed) {\n didTransform = true\n }\n },\n })\n },\n })\n\n return didTransform\n}\n\nexport function addSourceToJsx(\n code: string,\n id: string,\n ignore: {\n files?: Array<string | RegExp>\n components?: Array<string | RegExp>\n } = {},\n) {\n const [filePath] = id.split('?')\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n const location = filePath?.replace(normalizePath(process.cwd()), '')!\n\n const fileIgnored = matcher(ignore.files || [], location)\n if (fileIgnored) {\n return\n }\n try {\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n })\n const didTransform = transform(ast, location, ignore.components || [])\n if (!didTransform) {\n return\n }\n return gen(ast, {\n sourceMaps: true,\n retainLines: true,\n filename: id,\n sourceFileName: filePath,\n })\n } catch (e) {\n return\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const matcher: (patterns: Array<string | RegExp>, str: string) => boolean;
@@ -0,0 +1,18 @@
1
+ import picomatch from "picomatch";
2
+ const matcher = (patterns, str) => {
3
+ if (patterns.length === 0) {
4
+ return false;
5
+ }
6
+ const matchers = patterns.map((pattern) => {
7
+ if (typeof pattern === "string") {
8
+ return picomatch(pattern);
9
+ } else {
10
+ return (s) => pattern.test(s);
11
+ }
12
+ });
13
+ return matchers.some((isMatch) => isMatch(str));
14
+ };
15
+ export {
16
+ matcher
17
+ };
18
+ //# sourceMappingURL=matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.js","sources":["../../src/matcher.ts"],"sourcesContent":["import picomatch from 'picomatch'\n\nexport const matcher = (\n patterns: Array<string | RegExp>,\n str: string,\n): boolean => {\n if (patterns.length === 0) {\n return false\n }\n const matchers = patterns.map((pattern) => {\n if (typeof pattern === 'string') {\n return picomatch(pattern)\n } else {\n return (s: string) => pattern.test(s)\n }\n })\n\n return matchers.some((isMatch) => isMatch(str))\n}\n"],"names":[],"mappings":";AAEO,MAAM,UAAU,CACrB,UACA,QACY;AACZ,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,SAAS,IAAI,CAAC,YAAY;AACzC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,UAAU,OAAO;AAAA,IAC1B,OAAO;AACL,aAAO,CAAC,MAAc,QAAQ,KAAK,CAAC;AAAA,IACtC;AAAA,EACF,CAAC;AAED,SAAO,SAAS,KAAK,CAAC,YAAY,QAAQ,GAAG,CAAC;AAChD;"}
@@ -0,0 +1 @@
1
+ export {};
@@ -45,6 +45,13 @@ export type TanStackDevtoolsViteConfig = {
45
45
  * @default true
46
46
  */
47
47
  enabled: boolean;
48
+ /**
49
+ * List of files or patterns to ignore for source injection.
50
+ */
51
+ ignore?: {
52
+ files?: Array<string | RegExp>;
53
+ components?: Array<string | RegExp>;
54
+ };
48
55
  };
49
56
  };
50
57
  export declare const defineDevtoolsConfig: (config: TanStackDevtoolsViteConfig) => TanStackDevtoolsViteConfig;
@@ -29,7 +29,7 @@ const devtools = (args) => {
29
29
  transform(code, id) {
30
30
  if (id.includes("node_modules") || id.includes("?raw") || id.includes("dist") || id.includes("build"))
31
31
  return;
32
- return addSourceToJsx(code, id);
32
+ return addSourceToJsx(code, id, args?.injectSource?.ignore);
33
33
  }
34
34
  },
35
35
  {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { devtoolsEventClient } from '@tanstack/devtools-client'\nimport { ServerEventBus } from '@tanstack/devtools-event-bus/server'\nimport { normalizePath } from 'vite'\nimport chalk from 'chalk'\nimport { handleDevToolsViteRequest, readPackageJson } from './utils'\nimport { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'\nimport { removeDevtools } from './remove-devtools'\nimport { addSourceToJsx } from './inject-source'\nimport { enhanceConsoleLog } from './enhance-logs'\nimport { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'\nimport {\n addPluginToDevtools,\n emitOutdatedDeps,\n installPackage,\n} from './package-manager'\nimport type { Plugin } from 'vite'\nimport type { EditorConfig } from './editor'\nimport type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server'\n\nexport type TanStackDevtoolsViteConfig = {\n /**\n * Configuration for the editor integration. Defaults to opening in VS code\n */\n editor?: EditorConfig\n /**\n * The configuration options for the server event bus\n */\n eventBusConfig?: ServerEventBusConfig & {\n /**\n * Should the server event bus be enabled or not\n * @default true\n */\n enabled?: boolean // defaults to true\n }\n /**\n * Configuration for enhanced logging.\n */\n enhancedLogs?: {\n /**\n * Whether to enable enhanced logging.\n * @default true\n */\n enabled: boolean\n }\n /**\n * Whether to remove devtools from the production build.\n * @default true\n */\n removeDevtoolsOnBuild?: boolean\n\n /**\n * Whether to log information to the console.\n * @default true\n */\n logging?: boolean\n /**\n * Configuration for source injection.\n */\n injectSource?: {\n /**\n * Whether to enable source injection via data-tsd-source.\n * @default true\n */\n enabled: boolean\n }\n}\n\nexport const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) =>\n config\n\nexport const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {\n let port = 5173\n const logging = args?.logging ?? true\n const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true }\n const injectSourceConfig = args?.injectSource ?? { enabled: true }\n const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true\n const serverBusEnabled = args?.eventBusConfig?.enabled ?? true\n const bus = new ServerEventBus(args?.eventBusConfig)\n\n let devtoolsFileId: string | null = null\n\n return [\n {\n enforce: 'pre',\n name: '@tanstack/devtools:inject-source',\n apply(config) {\n return config.mode === 'development' && injectSourceConfig.enabled\n },\n transform(code, id) {\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build')\n )\n return\n\n return addSourceToJsx(code, id)\n },\n },\n {\n name: '@tanstack/devtools:config',\n enforce: 'pre',\n config(_, { command }) {\n // we do not apply any config changes for build\n if (command !== 'serve') {\n return\n }\n\n /* const solidDedupeDeps = [\n 'solid-js',\n 'solid-js/web',\n 'solid-js/store',\n 'solid-js/html',\n 'solid-js/h',\n ]\n\n return {\n resolve: {\n dedupe: solidDedupeDeps,\n },\n optimizeDeps: {\n include: solidDedupeDeps,\n },\n } */\n },\n },\n {\n enforce: 'pre',\n name: '@tanstack/devtools:custom-server',\n apply(config) {\n // Custom server is only needed in development for piping events to the client\n return config.mode === 'development'\n },\n configureServer(server) {\n if (serverBusEnabled) {\n bus.start()\n }\n\n server.middlewares.use((req, _res, next) => {\n if (req.socket.localPort && req.socket.localPort !== port) {\n port = req.socket.localPort\n }\n next()\n })\n if (server.config.server.port) {\n port = server.config.server.port\n }\n\n server.httpServer?.on('listening', () => {\n port = server.config.server.port\n })\n\n const editor = args?.editor ?? DEFAULT_EDITOR_CONFIG\n const openInEditor: EditorConfig['open'] = async (\n path,\n lineNum,\n columnNum,\n ) => {\n if (!path) {\n return\n }\n await editor.open(path, lineNum, columnNum)\n }\n server.middlewares.use((req, res, next) =>\n handleDevToolsViteRequest(req, res, next, (parsedData) => {\n const { data, routine } = parsedData\n if (routine === 'open-source') {\n return handleOpenSource({\n data: { type: data.type, data },\n openInEditor,\n })\n }\n return\n }),\n )\n },\n },\n {\n name: '@tanstack/devtools:remove-devtools-on-build',\n apply(config, { command }) {\n // Check both command and mode to support various hosting providers\n // Some providers (Cloudflare, Netlify, Heroku) might not use 'build' command\n // but will always set mode to 'production' for production builds\n return (\n (command !== 'serve' || config.mode === 'production') &&\n removeDevtoolsOnBuild\n )\n },\n enforce: 'pre',\n transform(code, id) {\n if (id.includes('node_modules') || id.includes('?raw')) return\n const transform = removeDevtools(code, id)\n if (!transform) return\n if (logging) {\n console.log(\n `\\n${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${id.replace(normalizePath(process.cwd()), '')}\\n`,\n )\n }\n return transform\n },\n },\n {\n name: '@tanstack/devtools:event-client-setup',\n apply(config, { command }) {\n if (\n process.env.CI ||\n process.env.NODE_ENV !== 'development' ||\n command !== 'serve'\n )\n return false\n return config.mode === 'development'\n },\n async configureServer() {\n const packageJson = await readPackageJson()\n const outdatedDeps = emitOutdatedDeps().then((deps) => deps)\n\n // Listen for package installation requests\n devtoolsEventClient.on('install-devtools', async (event) => {\n const result = await installPackage(event.payload.packageName)\n devtoolsEventClient.emit('devtools-installed', {\n packageName: event.payload.packageName,\n success: result.success,\n error: result.error,\n })\n\n // If installation was successful, automatically add the plugin to devtools\n if (result.success) {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`,\n ),\n )\n\n const injectResult = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n if (injectResult.success) {\n // Emit plugin-added event so the UI updates\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: true,\n })\n\n // Also re-read package.json to update the UI with the newly installed package\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n }\n }\n })\n\n // Listen for add plugin to devtools requests\n devtoolsEventClient.on('add-plugin-to-devtools', (event) => {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${packageName} to devtools...`,\n ),\n )\n\n const result = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: result.success,\n error: result.error,\n })\n })\n\n // Handle bump-package-version event\n devtoolsEventClient.on('bump-package-version', async (event) => {\n const {\n packageName,\n devtoolsPackage,\n pluginName,\n minVersion,\n pluginImport,\n } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`,\n ),\n )\n\n // Install the package with the minimum version\n const packageWithVersion = minVersion\n ? `${packageName}@^${minVersion}`\n : packageName\n\n const result = await installPackage(packageWithVersion)\n\n if (!result.success) {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: false,\n error: result.error,\n })\n return\n }\n\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`,\n ),\n )\n\n // Check if we found the devtools file\n if (!devtoolsFileId) {\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: true,\n })\n return\n }\n\n // Now inject the devtools plugin\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`,\n ),\n )\n\n const injectResult = injectPluginIntoFile(devtoolsFileId, {\n packageName: devtoolsPackage,\n pluginName,\n pluginImport,\n })\n\n if (injectResult.success) {\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: true,\n })\n\n // Re-read package.json to update the UI\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n } else {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: false,\n error: injectResult.error,\n })\n }\n })\n\n // whenever a client mounts we send all the current info to the subscribers\n devtoolsEventClient.on('mounted', async () => {\n devtoolsEventClient.emit('outdated-deps-read', {\n outdatedDeps: await outdatedDeps,\n })\n devtoolsEventClient.emit('package-json-read', {\n packageJson,\n })\n })\n },\n async handleHotUpdate({ file }) {\n if (file.endsWith('package.json')) {\n const newPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: newPackageJson,\n })\n emitOutdatedDeps()\n }\n },\n },\n {\n name: '@tanstack/devtools:better-console-logs',\n enforce: 'pre',\n apply(config) {\n return config.mode === 'development' && enhancedLogsConfig.enabled\n },\n transform(code, id) {\n // Ignore anything external\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build') ||\n !code.includes('console.')\n )\n return\n\n return enhanceConsoleLog(code, id, port)\n },\n },\n {\n name: '@tanstack/devtools:inject-plugin',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // First pass: find where TanStackDevtools is imported\n if (!devtoolsFileId && detectDevtoolsFile(code)) {\n // Extract actual file path (remove query params)\n const [filePath] = id.split('?')\n if (filePath) {\n devtoolsFileId = filePath\n }\n }\n\n return undefined\n },\n },\n ]\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { devtoolsEventClient } from '@tanstack/devtools-client'\nimport { ServerEventBus } from '@tanstack/devtools-event-bus/server'\nimport { normalizePath } from 'vite'\nimport chalk from 'chalk'\nimport { handleDevToolsViteRequest, readPackageJson } from './utils'\nimport { DEFAULT_EDITOR_CONFIG, handleOpenSource } from './editor'\nimport { removeDevtools } from './remove-devtools'\nimport { addSourceToJsx } from './inject-source'\nimport { enhanceConsoleLog } from './enhance-logs'\nimport { detectDevtoolsFile, injectPluginIntoFile } from './inject-plugin'\nimport {\n addPluginToDevtools,\n emitOutdatedDeps,\n installPackage,\n} from './package-manager'\nimport type { Plugin } from 'vite'\nimport type { EditorConfig } from './editor'\nimport type { ServerEventBusConfig } from '@tanstack/devtools-event-bus/server'\n\nexport type TanStackDevtoolsViteConfig = {\n /**\n * Configuration for the editor integration. Defaults to opening in VS code\n */\n editor?: EditorConfig\n /**\n * The configuration options for the server event bus\n */\n eventBusConfig?: ServerEventBusConfig & {\n /**\n * Should the server event bus be enabled or not\n * @default true\n */\n enabled?: boolean // defaults to true\n }\n /**\n * Configuration for enhanced logging.\n */\n enhancedLogs?: {\n /**\n * Whether to enable enhanced logging.\n * @default true\n */\n enabled: boolean\n }\n /**\n * Whether to remove devtools from the production build.\n * @default true\n */\n removeDevtoolsOnBuild?: boolean\n\n /**\n * Whether to log information to the console.\n * @default true\n */\n logging?: boolean\n /**\n * Configuration for source injection.\n */\n injectSource?: {\n /**\n * Whether to enable source injection via data-tsd-source.\n * @default true\n */\n enabled: boolean\n /**\n * List of files or patterns to ignore for source injection.\n */\n ignore?: {\n files?: Array<string | RegExp>\n components?: Array<string | RegExp>\n }\n }\n}\n\nexport const defineDevtoolsConfig = (config: TanStackDevtoolsViteConfig) =>\n config\n\nexport const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {\n let port = 5173\n const logging = args?.logging ?? true\n const enhancedLogsConfig = args?.enhancedLogs ?? { enabled: true }\n const injectSourceConfig = args?.injectSource ?? { enabled: true }\n const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true\n const serverBusEnabled = args?.eventBusConfig?.enabled ?? true\n const bus = new ServerEventBus(args?.eventBusConfig)\n\n let devtoolsFileId: string | null = null\n\n return [\n {\n enforce: 'pre',\n name: '@tanstack/devtools:inject-source',\n apply(config) {\n return config.mode === 'development' && injectSourceConfig.enabled\n },\n transform(code, id) {\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build')\n )\n return\n\n return addSourceToJsx(code, id, args?.injectSource?.ignore)\n },\n },\n {\n name: '@tanstack/devtools:config',\n enforce: 'pre',\n config(_, { command }) {\n // we do not apply any config changes for build\n if (command !== 'serve') {\n return\n }\n\n /* const solidDedupeDeps = [\n 'solid-js',\n 'solid-js/web',\n 'solid-js/store',\n 'solid-js/html',\n 'solid-js/h',\n ]\n\n return {\n resolve: {\n dedupe: solidDedupeDeps,\n },\n optimizeDeps: {\n include: solidDedupeDeps,\n },\n } */\n },\n },\n {\n enforce: 'pre',\n name: '@tanstack/devtools:custom-server',\n apply(config) {\n // Custom server is only needed in development for piping events to the client\n return config.mode === 'development'\n },\n configureServer(server) {\n if (serverBusEnabled) {\n bus.start()\n }\n\n server.middlewares.use((req, _res, next) => {\n if (req.socket.localPort && req.socket.localPort !== port) {\n port = req.socket.localPort\n }\n next()\n })\n if (server.config.server.port) {\n port = server.config.server.port\n }\n\n server.httpServer?.on('listening', () => {\n port = server.config.server.port\n })\n\n const editor = args?.editor ?? DEFAULT_EDITOR_CONFIG\n const openInEditor: EditorConfig['open'] = async (\n path,\n lineNum,\n columnNum,\n ) => {\n if (!path) {\n return\n }\n await editor.open(path, lineNum, columnNum)\n }\n server.middlewares.use((req, res, next) =>\n handleDevToolsViteRequest(req, res, next, (parsedData) => {\n const { data, routine } = parsedData\n if (routine === 'open-source') {\n return handleOpenSource({\n data: { type: data.type, data },\n openInEditor,\n })\n }\n return\n }),\n )\n },\n },\n {\n name: '@tanstack/devtools:remove-devtools-on-build',\n apply(config, { command }) {\n // Check both command and mode to support various hosting providers\n // Some providers (Cloudflare, Netlify, Heroku) might not use 'build' command\n // but will always set mode to 'production' for production builds\n return (\n (command !== 'serve' || config.mode === 'production') &&\n removeDevtoolsOnBuild\n )\n },\n enforce: 'pre',\n transform(code, id) {\n if (id.includes('node_modules') || id.includes('?raw')) return\n const transform = removeDevtools(code, id)\n if (!transform) return\n if (logging) {\n console.log(\n `\\n${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${id.replace(normalizePath(process.cwd()), '')}\\n`,\n )\n }\n return transform\n },\n },\n {\n name: '@tanstack/devtools:event-client-setup',\n apply(config, { command }) {\n if (\n process.env.CI ||\n process.env.NODE_ENV !== 'development' ||\n command !== 'serve'\n )\n return false\n return config.mode === 'development'\n },\n async configureServer() {\n const packageJson = await readPackageJson()\n const outdatedDeps = emitOutdatedDeps().then((deps) => deps)\n\n // Listen for package installation requests\n devtoolsEventClient.on('install-devtools', async (event) => {\n const result = await installPackage(event.payload.packageName)\n devtoolsEventClient.emit('devtools-installed', {\n packageName: event.payload.packageName,\n success: result.success,\n error: result.error,\n })\n\n // If installation was successful, automatically add the plugin to devtools\n if (result.success) {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`,\n ),\n )\n\n const injectResult = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n if (injectResult.success) {\n // Emit plugin-added event so the UI updates\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: true,\n })\n\n // Also re-read package.json to update the UI with the newly installed package\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n }\n }\n })\n\n // Listen for add plugin to devtools requests\n devtoolsEventClient.on('add-plugin-to-devtools', (event) => {\n const { packageName, pluginName, pluginImport } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${packageName} to devtools...`,\n ),\n )\n\n const result = addPluginToDevtools(\n devtoolsFileId,\n packageName,\n pluginName,\n pluginImport,\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName,\n success: result.success,\n error: result.error,\n })\n })\n\n // Handle bump-package-version event\n devtoolsEventClient.on('bump-package-version', async (event) => {\n const {\n packageName,\n devtoolsPackage,\n pluginName,\n minVersion,\n pluginImport,\n } = event.payload\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`,\n ),\n )\n\n // Install the package with the minimum version\n const packageWithVersion = minVersion\n ? `${packageName}@^${minVersion}`\n : packageName\n\n const result = await installPackage(packageWithVersion)\n\n if (!result.success) {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: false,\n error: result.error,\n })\n return\n }\n\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`,\n ),\n )\n\n // Check if we found the devtools file\n if (!devtoolsFileId) {\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`,\n ),\n )\n devtoolsEventClient.emit('devtools-installed', {\n packageName: devtoolsPackage,\n success: true,\n })\n return\n }\n\n // Now inject the devtools plugin\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`,\n ),\n )\n\n const injectResult = injectPluginIntoFile(devtoolsFileId, {\n packageName: devtoolsPackage,\n pluginName,\n pluginImport,\n })\n\n if (injectResult.success) {\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: true,\n })\n\n // Re-read package.json to update the UI\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: updatedPackageJson,\n })\n } else {\n console.log(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`,\n ),\n )\n\n devtoolsEventClient.emit('plugin-added', {\n packageName: devtoolsPackage,\n success: false,\n error: injectResult.error,\n })\n }\n })\n\n // whenever a client mounts we send all the current info to the subscribers\n devtoolsEventClient.on('mounted', async () => {\n devtoolsEventClient.emit('outdated-deps-read', {\n outdatedDeps: await outdatedDeps,\n })\n devtoolsEventClient.emit('package-json-read', {\n packageJson,\n })\n })\n },\n async handleHotUpdate({ file }) {\n if (file.endsWith('package.json')) {\n const newPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-read', {\n packageJson: newPackageJson,\n })\n emitOutdatedDeps()\n }\n },\n },\n {\n name: '@tanstack/devtools:better-console-logs',\n enforce: 'pre',\n apply(config) {\n return config.mode === 'development' && enhancedLogsConfig.enabled\n },\n transform(code, id) {\n // Ignore anything external\n if (\n id.includes('node_modules') ||\n id.includes('?raw') ||\n id.includes('dist') ||\n id.includes('build') ||\n !code.includes('console.')\n )\n return\n\n return enhanceConsoleLog(code, id, port)\n },\n },\n {\n name: '@tanstack/devtools:inject-plugin',\n apply(config, { command }) {\n return config.mode === 'development' && command === 'serve'\n },\n transform(code, id) {\n // First pass: find where TanStackDevtools is imported\n if (!devtoolsFileId && detectDevtoolsFile(code)) {\n // Extract actual file path (remove query params)\n const [filePath] = id.split('?')\n if (filePath) {\n devtoolsFileId = filePath\n }\n }\n\n return undefined\n },\n },\n ]\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/devtools-vite",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "TanStack Vite plugin used to enhance the core devtools with additional functionalities",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -48,13 +48,15 @@
48
48
  "@babel/types": "^7.28.4",
49
49
  "chalk": "^5.6.2",
50
50
  "launch-editor": "^2.11.1",
51
- "@tanstack/devtools-client": "0.0.3",
52
- "@tanstack/devtools-event-bus": "0.3.2"
51
+ "picomatch": "^4.0.3",
52
+ "@tanstack/devtools-event-bus": "0.3.2",
53
+ "@tanstack/devtools-client": "0.0.3"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/babel__core": "^7.20.5",
56
57
  "@types/babel__generator": "^7.27.0",
57
58
  "@types/babel__traverse": "^7.28.0",
59
+ "@types/picomatch": "^4.0.2",
58
60
  "happy-dom": "^18.0.1"
59
61
  },
60
62
  "scripts": {
@@ -854,4 +854,36 @@ function test({...rest}) {
854
854
  )
855
855
  })
856
856
  })
857
+
858
+ describe('ignore patterns', () => {
859
+ it('should skip injection for ignored component names (string)', () => {
860
+ const output = addSourceToJsx(
861
+ `
862
+ function test() {
863
+ return <Button />
864
+ }
865
+ `,
866
+ 'test.jsx',
867
+ {
868
+ components: ['Button'],
869
+ },
870
+ )
871
+ expect(output).toBe(undefined)
872
+ })
873
+
874
+ it('should skip injection for ignored file paths (glob)', () => {
875
+ const output = addSourceToJsx(
876
+ `
877
+ function test() {
878
+ return <div />
879
+ }
880
+ `,
881
+ 'src/components/ignored-file.jsx',
882
+ {
883
+ files: ['**/ignored-file.jsx'],
884
+ },
885
+ )
886
+ expect(output).toBe(undefined)
887
+ })
888
+ })
857
889
  })
@@ -1,5 +1,6 @@
1
1
  import { normalizePath } from 'vite'
2
2
  import { gen, parse, t, trav } from './babel'
3
+ import { matcher } from './matcher'
3
4
  import type { types as Babel, NodePath } from '@babel/core'
4
5
  import type { ParseResult } from '@babel/parser'
5
6
 
@@ -111,14 +112,19 @@ const transformJSX = (
111
112
  element: NodePath<t.JSXOpeningElement>,
112
113
  propsName: string | null,
113
114
  file: string,
115
+ ignorePatterns: Array<string | RegExp>,
114
116
  ) => {
115
117
  const loc = element.node.loc
116
118
  if (!loc) return
117
119
  const line = loc.start.line
118
120
  const column = loc.start.column
119
121
  const nameOfElement = getNameOfElement(element.node.name)
120
-
121
- if (nameOfElement === 'Fragment' || nameOfElement === 'React.Fragment') {
122
+ const isIgnored = matcher(ignorePatterns, nameOfElement)
123
+ if (
124
+ nameOfElement === 'Fragment' ||
125
+ nameOfElement === 'React.Fragment' ||
126
+ isIgnored
127
+ ) {
122
128
  return
123
129
  }
124
130
  const hasDataSource = element.node.attributes.some(
@@ -151,7 +157,11 @@ const transformJSX = (
151
157
  return true
152
158
  }
153
159
 
154
- const transform = (ast: ParseResult<Babel.File>, file: string) => {
160
+ const transform = (
161
+ ast: ParseResult<Babel.File>,
162
+ file: string,
163
+ ignorePatterns: Array<string | RegExp>,
164
+ ) => {
155
165
  let didTransform = false
156
166
 
157
167
  trav(ast, {
@@ -161,7 +171,12 @@ const transform = (ast: ParseResult<Babel.File>, file: string) => {
161
171
  )
162
172
  functionDeclaration.traverse({
163
173
  JSXOpeningElement(element) {
164
- const transformed = transformJSX(element, propsName, file)
174
+ const transformed = transformJSX(
175
+ element,
176
+ propsName,
177
+ file,
178
+ ignorePatterns,
179
+ )
165
180
  if (transformed) {
166
181
  didTransform = true
167
182
  }
@@ -172,7 +187,12 @@ const transform = (ast: ParseResult<Babel.File>, file: string) => {
172
187
  const propsName = getPropsNameFromFunctionDeclaration(path.node)
173
188
  path.traverse({
174
189
  JSXOpeningElement(element) {
175
- const transformed = transformJSX(element, propsName, file)
190
+ const transformed = transformJSX(
191
+ element,
192
+ propsName,
193
+ file,
194
+ ignorePatterns,
195
+ )
176
196
  if (transformed) {
177
197
  didTransform = true
178
198
  }
@@ -183,7 +203,12 @@ const transform = (ast: ParseResult<Babel.File>, file: string) => {
183
203
  const propsName = getPropsNameFromFunctionDeclaration(path.node)
184
204
  path.traverse({
185
205
  JSXOpeningElement(element) {
186
- const transformed = transformJSX(element, propsName, file)
206
+ const transformed = transformJSX(
207
+ element,
208
+ propsName,
209
+ file,
210
+ ignorePatterns,
211
+ )
187
212
  if (transformed) {
188
213
  didTransform = true
189
214
  }
@@ -204,7 +229,12 @@ const transform = (ast: ParseResult<Babel.File>, file: string) => {
204
229
 
205
230
  path.traverse({
206
231
  JSXOpeningElement(element) {
207
- const transformed = transformJSX(element, propsName, file)
232
+ const transformed = transformJSX(
233
+ element,
234
+ propsName,
235
+ file,
236
+ ignorePatterns,
237
+ )
208
238
  if (transformed) {
209
239
  didTransform = true
210
240
  }
@@ -216,17 +246,28 @@ const transform = (ast: ParseResult<Babel.File>, file: string) => {
216
246
  return didTransform
217
247
  }
218
248
 
219
- export function addSourceToJsx(code: string, id: string) {
249
+ export function addSourceToJsx(
250
+ code: string,
251
+ id: string,
252
+ ignore: {
253
+ files?: Array<string | RegExp>
254
+ components?: Array<string | RegExp>
255
+ } = {},
256
+ ) {
220
257
  const [filePath] = id.split('?')
221
258
  // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
222
259
  const location = filePath?.replace(normalizePath(process.cwd()), '')!
223
260
 
261
+ const fileIgnored = matcher(ignore.files || [], location)
262
+ if (fileIgnored) {
263
+ return
264
+ }
224
265
  try {
225
266
  const ast = parse(code, {
226
267
  sourceType: 'module',
227
268
  plugins: ['jsx', 'typescript'],
228
269
  })
229
- const didTransform = transform(ast, location)
270
+ const didTransform = transform(ast, location, ignore.components || [])
230
271
  if (!didTransform) {
231
272
  return
232
273
  }
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { matcher } from './matcher'
3
+
4
+ describe('matcher', () => {
5
+ it('returns false when patterns is empty', () => {
6
+ expect(matcher([], 'foo')).toBe(false)
7
+ })
8
+
9
+ it('matches string patterns against component names', () => {
10
+ const patterns = ['Button', 'MyComponent']
11
+ expect(matcher(patterns, 'Button')).toBe(true)
12
+ expect(matcher(patterns, 'Other')).toBe(false)
13
+ })
14
+
15
+ it('matches regex patterns against component names', () => {
16
+ const patterns = [/^Button$/, /Comp/]
17
+ expect(matcher(patterns, 'Button')).toBe(true)
18
+ expect(matcher(patterns, 'MyComp')).toBe(true)
19
+ expect(matcher(patterns, 'NoMatch')).toBe(false)
20
+ })
21
+
22
+ it('matches file paths with glob patterns', () => {
23
+ const patterns = ['**/ignored-file.jsx']
24
+ expect(matcher(patterns, 'src/components/ignored-file.jsx')).toBe(true)
25
+ expect(matcher(patterns, 'src/components/other.jsx')).toBe(false)
26
+ })
27
+
28
+ it('matches file paths with regex', () => {
29
+ const patterns = [/ignored-file\.jsx$/]
30
+ expect(matcher(patterns, 'src/components/ignored-file.jsx')).toBe(true)
31
+ expect(matcher(patterns, 'src/components/other.jsx')).toBe(false)
32
+ })
33
+ })
package/src/matcher.ts ADDED
@@ -0,0 +1,19 @@
1
+ import picomatch from 'picomatch'
2
+
3
+ export const matcher = (
4
+ patterns: Array<string | RegExp>,
5
+ str: string,
6
+ ): boolean => {
7
+ if (patterns.length === 0) {
8
+ return false
9
+ }
10
+ const matchers = patterns.map((pattern) => {
11
+ if (typeof pattern === 'string') {
12
+ return picomatch(pattern)
13
+ } else {
14
+ return (s: string) => pattern.test(s)
15
+ }
16
+ })
17
+
18
+ return matchers.some((isMatch) => isMatch(str))
19
+ }
package/src/plugin.ts CHANGED
@@ -62,6 +62,13 @@ export type TanStackDevtoolsViteConfig = {
62
62
  * @default true
63
63
  */
64
64
  enabled: boolean
65
+ /**
66
+ * List of files or patterns to ignore for source injection.
67
+ */
68
+ ignore?: {
69
+ files?: Array<string | RegExp>
70
+ components?: Array<string | RegExp>
71
+ }
65
72
  }
66
73
  }
67
74
 
@@ -95,7 +102,7 @@ export const devtools = (args?: TanStackDevtoolsViteConfig): Array<Plugin> => {
95
102
  )
96
103
  return
97
104
 
98
- return addSourceToJsx(code, id)
105
+ return addSourceToJsx(code, id, args?.injectSource?.ignore)
99
106
  },
100
107
  },
101
108
  {