@tanstack/devtools-vite 0.3.6 → 0.3.7
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/esm/inject-plugin.d.ts +21 -0
- package/dist/esm/inject-plugin.js +228 -0
- package/dist/esm/inject-plugin.js.map +1 -0
- package/dist/esm/inject-plugin.test.d.ts +1 -0
- package/dist/esm/package-manager.d.ts +16 -0
- package/dist/esm/package-manager.js +139 -0
- package/dist/esm/package-manager.js.map +1 -0
- package/dist/esm/plugin.js +152 -18
- package/dist/esm/plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/inject-plugin.test.ts +1086 -0
- package/src/inject-plugin.ts +343 -0
- package/src/package-manager.ts +181 -0
- package/src/plugin.ts +195 -25
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PluginInjection } from '@tanstack/devtools-client';
|
|
2
|
+
import { types as Babel } from '@babel/core';
|
|
3
|
+
import { ParseResult } from '@babel/parser';
|
|
4
|
+
/**
|
|
5
|
+
* Finds the TanStackDevtools component name in the file
|
|
6
|
+
* Handles renamed imports and namespace imports
|
|
7
|
+
*/
|
|
8
|
+
export declare const findDevtoolsComponentName: (ast: ParseResult<Babel.File>) => string | null;
|
|
9
|
+
export declare const transformAndInject: (ast: ParseResult<Babel.File>, injection: PluginInjection, devtoolsComponentName: string) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Detects if a file contains TanStack devtools import
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectDevtoolsFile(code: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Injects a plugin into the TanStackDevtools component in a file
|
|
16
|
+
* Reads the file, transforms it, and writes it back
|
|
17
|
+
*/
|
|
18
|
+
export declare function injectPluginIntoFile(filePath: string, injection: PluginInjection): {
|
|
19
|
+
success: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { gen, trav } from "./babel.js";
|
|
3
|
+
import { parse } from "@babel/parser";
|
|
4
|
+
import * as t from "@babel/types";
|
|
5
|
+
const detectDevtoolsImport = (code) => {
|
|
6
|
+
const devtoolsPackages = [
|
|
7
|
+
"@tanstack/react-devtools",
|
|
8
|
+
"@tanstack/solid-devtools",
|
|
9
|
+
"@tanstack/vue-devtools",
|
|
10
|
+
"@tanstack/svelte-devtools",
|
|
11
|
+
"@tanstack/angular-devtools"
|
|
12
|
+
];
|
|
13
|
+
try {
|
|
14
|
+
const ast = parse(code, {
|
|
15
|
+
sourceType: "module",
|
|
16
|
+
plugins: ["jsx", "typescript"]
|
|
17
|
+
});
|
|
18
|
+
let hasDevtoolsImport = false;
|
|
19
|
+
trav(ast, {
|
|
20
|
+
ImportDeclaration(path) {
|
|
21
|
+
const importSource = path.node.source.value;
|
|
22
|
+
if (devtoolsPackages.includes(importSource)) {
|
|
23
|
+
hasDevtoolsImport = true;
|
|
24
|
+
path.stop();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return hasDevtoolsImport;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const findDevtoolsComponentName = (ast) => {
|
|
34
|
+
let componentName = null;
|
|
35
|
+
const devtoolsPackages = [
|
|
36
|
+
"@tanstack/react-devtools",
|
|
37
|
+
"@tanstack/solid-devtools",
|
|
38
|
+
"@tanstack/vue-devtools",
|
|
39
|
+
"@tanstack/svelte-devtools",
|
|
40
|
+
"@tanstack/angular-devtools"
|
|
41
|
+
];
|
|
42
|
+
trav(ast, {
|
|
43
|
+
ImportDeclaration(path) {
|
|
44
|
+
const importSource = path.node.source.value;
|
|
45
|
+
if (devtoolsPackages.includes(importSource)) {
|
|
46
|
+
const namedImport = path.node.specifiers.find(
|
|
47
|
+
(spec) => t.isImportSpecifier(spec) && t.isIdentifier(spec.imported) && spec.imported.name === "TanStackDevtools"
|
|
48
|
+
);
|
|
49
|
+
if (namedImport && t.isImportSpecifier(namedImport)) {
|
|
50
|
+
componentName = namedImport.local.name;
|
|
51
|
+
path.stop();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const namespaceImport = path.node.specifiers.find(
|
|
55
|
+
(spec) => t.isImportNamespaceSpecifier(spec)
|
|
56
|
+
);
|
|
57
|
+
if (namespaceImport && t.isImportNamespaceSpecifier(namespaceImport)) {
|
|
58
|
+
componentName = `${namespaceImport.local.name}.TanStackDevtools`;
|
|
59
|
+
path.stop();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return componentName;
|
|
66
|
+
};
|
|
67
|
+
const transformAndInject = (ast, injection, devtoolsComponentName) => {
|
|
68
|
+
let didTransform = false;
|
|
69
|
+
const importName = injection.pluginImport?.importName;
|
|
70
|
+
const pluginType = injection.pluginImport?.type || "jsx";
|
|
71
|
+
const displayName = injection.pluginName;
|
|
72
|
+
if (!importName) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const isNamespaceImport = devtoolsComponentName.includes(".");
|
|
76
|
+
trav(ast, {
|
|
77
|
+
JSXOpeningElement(path) {
|
|
78
|
+
const elementName = path.node.name;
|
|
79
|
+
let matches = false;
|
|
80
|
+
if (isNamespaceImport) {
|
|
81
|
+
if (t.isJSXMemberExpression(elementName)) {
|
|
82
|
+
const fullName = `${t.isJSXIdentifier(elementName.object) ? elementName.object.name : ""}.${t.isJSXIdentifier(elementName.property) ? elementName.property.name : ""}`;
|
|
83
|
+
matches = fullName === devtoolsComponentName;
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
matches = t.isJSXIdentifier(elementName) && elementName.name === devtoolsComponentName;
|
|
87
|
+
}
|
|
88
|
+
if (matches) {
|
|
89
|
+
const pluginsProp = path.node.attributes.find(
|
|
90
|
+
(attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === "plugins"
|
|
91
|
+
);
|
|
92
|
+
if (pluginsProp && t.isJSXAttribute(pluginsProp)) {
|
|
93
|
+
if (pluginsProp.value && t.isJSXExpressionContainer(pluginsProp.value)) {
|
|
94
|
+
const expression = pluginsProp.value.expression;
|
|
95
|
+
if (t.isArrayExpression(expression)) {
|
|
96
|
+
const pluginExists = expression.elements.some((element) => {
|
|
97
|
+
if (!element) return false;
|
|
98
|
+
if (pluginType === "function") {
|
|
99
|
+
return t.isCallExpression(element) && t.isIdentifier(element.callee) && element.callee.name === importName;
|
|
100
|
+
}
|
|
101
|
+
if (!t.isObjectExpression(element)) return false;
|
|
102
|
+
return element.properties.some((prop) => {
|
|
103
|
+
if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key) || prop.key.name !== "name") {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return t.isStringLiteral(prop.value) && prop.value.value === displayName;
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
if (!pluginExists) {
|
|
110
|
+
if (pluginType === "function") {
|
|
111
|
+
expression.elements.push(
|
|
112
|
+
t.callExpression(t.identifier(importName), [])
|
|
113
|
+
);
|
|
114
|
+
} else {
|
|
115
|
+
const renderValue = t.jsxElement(
|
|
116
|
+
t.jsxOpeningElement(t.jsxIdentifier(importName), [], true),
|
|
117
|
+
null,
|
|
118
|
+
[],
|
|
119
|
+
true
|
|
120
|
+
);
|
|
121
|
+
expression.elements.push(
|
|
122
|
+
t.objectExpression([
|
|
123
|
+
t.objectProperty(
|
|
124
|
+
t.identifier("name"),
|
|
125
|
+
t.stringLiteral(displayName)
|
|
126
|
+
),
|
|
127
|
+
t.objectProperty(t.identifier("render"), renderValue)
|
|
128
|
+
])
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
didTransform = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
let pluginElement;
|
|
137
|
+
if (pluginType === "function") {
|
|
138
|
+
pluginElement = t.callExpression(t.identifier(importName), []);
|
|
139
|
+
} else {
|
|
140
|
+
const renderValue = t.jsxElement(
|
|
141
|
+
t.jsxOpeningElement(t.jsxIdentifier(importName), [], true),
|
|
142
|
+
null,
|
|
143
|
+
[],
|
|
144
|
+
true
|
|
145
|
+
);
|
|
146
|
+
pluginElement = t.objectExpression([
|
|
147
|
+
t.objectProperty(
|
|
148
|
+
t.identifier("name"),
|
|
149
|
+
t.stringLiteral(displayName)
|
|
150
|
+
),
|
|
151
|
+
t.objectProperty(t.identifier("render"), renderValue)
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
path.node.attributes.push(
|
|
155
|
+
t.jsxAttribute(
|
|
156
|
+
t.jsxIdentifier("plugins"),
|
|
157
|
+
t.jsxExpressionContainer(t.arrayExpression([pluginElement]))
|
|
158
|
+
)
|
|
159
|
+
);
|
|
160
|
+
didTransform = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
if (didTransform) {
|
|
166
|
+
const importDeclaration = t.importDeclaration(
|
|
167
|
+
[t.importSpecifier(t.identifier(importName), t.identifier(importName))],
|
|
168
|
+
t.stringLiteral(injection.packageName)
|
|
169
|
+
);
|
|
170
|
+
let lastImportIndex = -1;
|
|
171
|
+
ast.program.body.forEach((node, index) => {
|
|
172
|
+
if (t.isImportDeclaration(node)) {
|
|
173
|
+
lastImportIndex = index;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
ast.program.body.splice(lastImportIndex + 1, 0, importDeclaration);
|
|
177
|
+
}
|
|
178
|
+
return didTransform;
|
|
179
|
+
};
|
|
180
|
+
function detectDevtoolsFile(code) {
|
|
181
|
+
return detectDevtoolsImport(code);
|
|
182
|
+
}
|
|
183
|
+
function injectPluginIntoFile(filePath, injection) {
|
|
184
|
+
try {
|
|
185
|
+
const code = readFileSync(filePath, "utf-8");
|
|
186
|
+
const ast = parse(code, {
|
|
187
|
+
sourceType: "module",
|
|
188
|
+
plugins: ["jsx", "typescript"]
|
|
189
|
+
});
|
|
190
|
+
const devtoolsComponentName = findDevtoolsComponentName(ast);
|
|
191
|
+
if (!devtoolsComponentName) {
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
error: "Could not find TanStackDevtools import"
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const didTransform = transformAndInject(
|
|
198
|
+
ast,
|
|
199
|
+
injection,
|
|
200
|
+
devtoolsComponentName
|
|
201
|
+
);
|
|
202
|
+
if (!didTransform) {
|
|
203
|
+
return {
|
|
204
|
+
success: false,
|
|
205
|
+
error: "Plugin already exists or no TanStackDevtools component found"
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const result = gen(ast, {
|
|
209
|
+
sourceMaps: false,
|
|
210
|
+
retainLines: false
|
|
211
|
+
});
|
|
212
|
+
writeFileSync(filePath, result.code, "utf-8");
|
|
213
|
+
return { success: true };
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error("Error injecting plugin:", e);
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
error: e instanceof Error ? e.message : "Unknown error"
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
export {
|
|
223
|
+
detectDevtoolsFile,
|
|
224
|
+
findDevtoolsComponentName,
|
|
225
|
+
injectPluginIntoFile,
|
|
226
|
+
transformAndInject
|
|
227
|
+
};
|
|
228
|
+
//# sourceMappingURL=inject-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-plugin.js","sources":["../../src/inject-plugin.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs'\nimport { gen, parse, t, trav } from './babel'\nimport type { PluginInjection } from '@tanstack/devtools-client'\nimport type { types as Babel } from '@babel/core'\nimport type { ParseResult } from '@babel/parser'\n\n/**\n * Detects if a file imports TanStack devtools packages\n * Handles: import X from '@tanstack/react-devtools'\n * import * as X from '@tanstack/react-devtools'\n * import { TanStackDevtools } from '@tanstack/react-devtools'\n */\nconst detectDevtoolsImport = (code: string): boolean => {\n const devtoolsPackages = [\n '@tanstack/react-devtools',\n '@tanstack/solid-devtools',\n '@tanstack/vue-devtools',\n '@tanstack/svelte-devtools',\n '@tanstack/angular-devtools',\n ]\n\n try {\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n })\n\n let hasDevtoolsImport = false\n\n trav(ast, {\n ImportDeclaration(path) {\n const importSource = path.node.source.value\n if (devtoolsPackages.includes(importSource)) {\n hasDevtoolsImport = true\n path.stop()\n }\n },\n })\n\n return hasDevtoolsImport\n } catch (e) {\n return false\n }\n}\n\n/**\n * Finds the TanStackDevtools component name in the file\n * Handles renamed imports and namespace imports\n */\nexport const findDevtoolsComponentName = (\n ast: ParseResult<Babel.File>,\n): string | null => {\n let componentName: string | null = null\n const devtoolsPackages = [\n '@tanstack/react-devtools',\n '@tanstack/solid-devtools',\n '@tanstack/vue-devtools',\n '@tanstack/svelte-devtools',\n '@tanstack/angular-devtools',\n ]\n\n trav(ast, {\n ImportDeclaration(path) {\n const importSource = path.node.source.value\n if (devtoolsPackages.includes(importSource)) {\n // Check for: import { TanStackDevtools } from '@tanstack/...'\n const namedImport = path.node.specifiers.find(\n (spec) =>\n t.isImportSpecifier(spec) &&\n t.isIdentifier(spec.imported) &&\n spec.imported.name === 'TanStackDevtools',\n )\n if (namedImport && t.isImportSpecifier(namedImport)) {\n componentName = namedImport.local.name\n path.stop()\n return\n }\n\n // Check for: import * as DevtoolsName from '@tanstack/...'\n const namespaceImport = path.node.specifiers.find((spec) =>\n t.isImportNamespaceSpecifier(spec),\n )\n if (namespaceImport && t.isImportNamespaceSpecifier(namespaceImport)) {\n // For namespace imports, we need to look for DevtoolsName.TanStackDevtools\n componentName = `${namespaceImport.local.name}.TanStackDevtools`\n path.stop()\n return\n }\n }\n },\n })\n\n return componentName\n}\n\nexport const transformAndInject = (\n ast: ParseResult<Babel.File>,\n injection: PluginInjection,\n devtoolsComponentName: string,\n) => {\n let didTransform = false\n\n // Use pluginImport if provided, otherwise generate from package name\n const importName = injection.pluginImport?.importName\n const pluginType = injection.pluginImport?.type || 'jsx'\n const displayName = injection.pluginName\n\n if (!importName) {\n return false\n }\n // Handle namespace imports like DevtoolsModule.TanStackDevtools\n const isNamespaceImport = devtoolsComponentName.includes('.')\n\n // Find and modify the TanStackDevtools JSX element\n trav(ast, {\n JSXOpeningElement(path) {\n const elementName = path.node.name\n let matches = false\n\n if (isNamespaceImport) {\n // Handle <DevtoolsModule.TanStackDevtools />\n if (t.isJSXMemberExpression(elementName)) {\n const fullName = `${t.isJSXIdentifier(elementName.object) ? elementName.object.name : ''}.${t.isJSXIdentifier(elementName.property) ? elementName.property.name : ''}`\n matches = fullName === devtoolsComponentName\n }\n } else {\n // Handle <TanStackDevtools /> or <RenamedDevtools />\n matches =\n t.isJSXIdentifier(elementName) &&\n elementName.name === devtoolsComponentName\n }\n\n if (matches) {\n // Find the plugins prop\n const pluginsProp = path.node.attributes.find(\n (attr) =>\n t.isJSXAttribute(attr) &&\n t.isJSXIdentifier(attr.name) &&\n attr.name.name === 'plugins',\n )\n // plugins found\n if (pluginsProp && t.isJSXAttribute(pluginsProp)) {\n // Check if plugins prop has a value\n if (\n pluginsProp.value &&\n t.isJSXExpressionContainer(pluginsProp.value)\n ) {\n const expression = pluginsProp.value.expression\n\n // If it's an array expression, add our plugin to it\n if (t.isArrayExpression(expression)) {\n // Check if plugin already exists\n const pluginExists = expression.elements.some((element) => {\n if (!element) return false\n\n // For function-based plugins, check if the function call exists\n if (pluginType === 'function') {\n return (\n t.isCallExpression(element) &&\n t.isIdentifier(element.callee) &&\n element.callee.name === importName\n )\n }\n\n // For JSX plugins, check object with name property\n if (!t.isObjectExpression(element)) return false\n\n return element.properties.some((prop) => {\n if (\n !t.isObjectProperty(prop) ||\n !t.isIdentifier(prop.key) ||\n prop.key.name !== 'name'\n ) {\n return false\n }\n\n return (\n t.isStringLiteral(prop.value) &&\n prop.value.value === displayName\n )\n })\n })\n\n if (!pluginExists) {\n // For function-based plugins, add them directly as function calls\n // For JSX plugins, wrap them in objects with name and render\n if (pluginType === 'function') {\n // Add directly: FormDevtoolsPlugin()\n expression.elements.push(\n t.callExpression(t.identifier(importName), []),\n )\n } else {\n // Add as object: { name: \"...\", render: <Component /> }\n const renderValue = t.jsxElement(\n t.jsxOpeningElement(t.jsxIdentifier(importName), [], true),\n null,\n [],\n true,\n )\n\n expression.elements.push(\n t.objectExpression([\n t.objectProperty(\n t.identifier('name'),\n t.stringLiteral(displayName),\n ),\n t.objectProperty(t.identifier('render'), renderValue),\n ]),\n )\n }\n\n didTransform = true\n }\n }\n }\n } else {\n // No plugins prop exists, create one with our plugin\n // For function-based plugins, add them directly as function calls\n // For JSX plugins, wrap them in objects with name and render\n let pluginElement\n if (pluginType === 'function') {\n // Add directly: plugins={[FormDevtoolsPlugin()]}\n pluginElement = t.callExpression(t.identifier(importName), [])\n } else {\n // Add as object: plugins={[{ name: \"...\", render: <Component /> }]}\n const renderValue = t.jsxElement(\n t.jsxOpeningElement(t.jsxIdentifier(importName), [], true),\n null,\n [],\n true,\n )\n\n pluginElement = t.objectExpression([\n t.objectProperty(\n t.identifier('name'),\n t.stringLiteral(displayName),\n ),\n t.objectProperty(t.identifier('render'), renderValue),\n ])\n }\n\n path.node.attributes.push(\n t.jsxAttribute(\n t.jsxIdentifier('plugins'),\n t.jsxExpressionContainer(t.arrayExpression([pluginElement])),\n ),\n )\n\n didTransform = true\n }\n }\n },\n })\n\n // Add import at the top of the file if transform happened\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (didTransform) {\n const importDeclaration = t.importDeclaration(\n [t.importSpecifier(t.identifier(importName), t.identifier(importName))],\n t.stringLiteral(injection.packageName),\n )\n\n // Find the last import declaration\n let lastImportIndex = -1\n ast.program.body.forEach((node, index) => {\n if (t.isImportDeclaration(node)) {\n lastImportIndex = index\n }\n })\n\n // Insert after the last import or at the beginning\n ast.program.body.splice(lastImportIndex + 1, 0, importDeclaration)\n }\n\n return didTransform\n}\n\n/**\n * Detects if a file contains TanStack devtools import\n */\nexport function detectDevtoolsFile(code: string): boolean {\n return detectDevtoolsImport(code)\n}\n\n/**\n * Injects a plugin into the TanStackDevtools component in a file\n * Reads the file, transforms it, and writes it back\n */\nexport function injectPluginIntoFile(\n filePath: string,\n injection: PluginInjection,\n): { success: boolean; error?: string } {\n try {\n // Read the file\n const code = readFileSync(filePath, 'utf-8')\n\n // Parse the code\n const ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n })\n\n // Find the devtools component name (handles renamed imports)\n const devtoolsComponentName = findDevtoolsComponentName(ast)\n if (!devtoolsComponentName) {\n return {\n success: false,\n error: 'Could not find TanStackDevtools import',\n }\n }\n\n // Transform and inject\n const didTransform = transformAndInject(\n ast,\n injection,\n devtoolsComponentName,\n )\n\n if (!didTransform) {\n return {\n success: false,\n error: 'Plugin already exists or no TanStackDevtools component found',\n }\n }\n\n // Generate the new code\n const result = gen(ast, {\n sourceMaps: false,\n retainLines: false,\n })\n\n // Write back to file\n writeFileSync(filePath, result.code, 'utf-8')\n\n return { success: true }\n } catch (e) {\n console.error('Error injecting plugin:', e)\n return {\n success: false,\n error: e instanceof Error ? e.message : 'Unknown error',\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OutdatedDeps } from '@tanstack/devtools-client';
|
|
2
|
+
/**
|
|
3
|
+
* Adds a plugin to the devtools configuration file
|
|
4
|
+
*/
|
|
5
|
+
export declare const addPluginToDevtools: (devtoolsFileId: string | null, packageName: string, pluginName: string, pluginImport?: {
|
|
6
|
+
importName: string;
|
|
7
|
+
type: "jsx" | "function";
|
|
8
|
+
}) => {
|
|
9
|
+
success: boolean;
|
|
10
|
+
error?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const installPackage: (packageName: string) => Promise<{
|
|
13
|
+
success: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const emitOutdatedDeps: () => Promise<OutdatedDeps | null>;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { devtoolsEventClient } from "@tanstack/devtools-client";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { tryParseJson, readPackageJson } from "./utils.js";
|
|
7
|
+
import { injectPluginIntoFile } from "./inject-plugin.js";
|
|
8
|
+
const getOutdatedCommand = (packageManager) => {
|
|
9
|
+
switch (packageManager) {
|
|
10
|
+
case "yarn":
|
|
11
|
+
return "yarn outdated --json";
|
|
12
|
+
case "pnpm":
|
|
13
|
+
return "pnpm outdated --format json";
|
|
14
|
+
case "bun":
|
|
15
|
+
return "bun outdated --json";
|
|
16
|
+
case "npm":
|
|
17
|
+
default:
|
|
18
|
+
return "npm outdated --json";
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const addPluginToDevtools = (devtoolsFileId, packageName, pluginName, pluginImport) => {
|
|
22
|
+
if (!devtoolsFileId) {
|
|
23
|
+
const error = "Devtools file not found";
|
|
24
|
+
console.log(
|
|
25
|
+
chalk.yellowBright(
|
|
26
|
+
`[@tanstack/devtools-vite] Could not add plugin. ${error}.`
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
return { success: false, error };
|
|
30
|
+
}
|
|
31
|
+
const result = injectPluginIntoFile(devtoolsFileId, {
|
|
32
|
+
packageName,
|
|
33
|
+
pluginName,
|
|
34
|
+
pluginImport
|
|
35
|
+
});
|
|
36
|
+
if (result.success) {
|
|
37
|
+
console.log(
|
|
38
|
+
chalk.greenBright(
|
|
39
|
+
`[@tanstack/devtools-vite] Successfully added ${packageName} to devtools!`
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
} else {
|
|
43
|
+
console.log(
|
|
44
|
+
chalk.yellowBright(
|
|
45
|
+
`[@tanstack/devtools-vite] Could not add plugin: ${result.error}`
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
const getInstallCommand = (packageManager, packageName) => {
|
|
52
|
+
switch (packageManager) {
|
|
53
|
+
case "yarn":
|
|
54
|
+
return `yarn add -D ${packageName}`;
|
|
55
|
+
case "pnpm":
|
|
56
|
+
return `pnpm add -D ${packageName}`;
|
|
57
|
+
case "bun":
|
|
58
|
+
return `bun add -D ${packageName}`;
|
|
59
|
+
case "npm":
|
|
60
|
+
default:
|
|
61
|
+
return `npm install -D ${packageName}`;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const installPackage = async (packageName) => {
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
const packageManager = detectPackageManager();
|
|
67
|
+
const installCommand = getInstallCommand(packageManager, packageName);
|
|
68
|
+
console.log(
|
|
69
|
+
chalk.blueBright(
|
|
70
|
+
`[@tanstack/devtools-vite] Installing ${packageName}...`
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
exec(installCommand, async (installError) => {
|
|
74
|
+
if (installError) {
|
|
75
|
+
console.error(
|
|
76
|
+
chalk.redBright(
|
|
77
|
+
`[@tanstack/devtools-vite] Failed to install ${packageName}:`
|
|
78
|
+
),
|
|
79
|
+
installError.message
|
|
80
|
+
);
|
|
81
|
+
resolve({
|
|
82
|
+
success: false,
|
|
83
|
+
error: installError.message
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(
|
|
88
|
+
chalk.greenBright(
|
|
89
|
+
`[@tanstack/devtools-vite] Successfully installed ${packageName}`
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
const updatedPackageJson = await readPackageJson();
|
|
93
|
+
devtoolsEventClient.emit("package-json-updated", {
|
|
94
|
+
packageJson: updatedPackageJson
|
|
95
|
+
});
|
|
96
|
+
resolve({ success: true });
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const detectPackageManager = () => {
|
|
101
|
+
const cwd = process.cwd();
|
|
102
|
+
if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock"))) {
|
|
103
|
+
return "bun";
|
|
104
|
+
}
|
|
105
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
|
|
106
|
+
return "pnpm";
|
|
107
|
+
}
|
|
108
|
+
if (existsSync(join(cwd, "yarn.lock"))) {
|
|
109
|
+
return "yarn";
|
|
110
|
+
}
|
|
111
|
+
if (existsSync(join(cwd, "package-lock.json"))) {
|
|
112
|
+
return "npm";
|
|
113
|
+
}
|
|
114
|
+
return "pnpm";
|
|
115
|
+
};
|
|
116
|
+
const emitOutdatedDeps = async () => {
|
|
117
|
+
return await new Promise((resolve) => {
|
|
118
|
+
const packageManager = detectPackageManager();
|
|
119
|
+
const outdatedCommand = getOutdatedCommand(packageManager);
|
|
120
|
+
exec(outdatedCommand, (_, stdout) => {
|
|
121
|
+
if (stdout) {
|
|
122
|
+
const newOutdatedDeps = tryParseJson(stdout);
|
|
123
|
+
if (!newOutdatedDeps) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
devtoolsEventClient.emit("outdated-deps-read", {
|
|
127
|
+
outdatedDeps: newOutdatedDeps
|
|
128
|
+
});
|
|
129
|
+
resolve(newOutdatedDeps);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
export {
|
|
135
|
+
addPluginToDevtools,
|
|
136
|
+
emitOutdatedDeps,
|
|
137
|
+
installPackage
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=package-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager.js","sources":["../../src/package-manager.ts"],"sourcesContent":["import { exec } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { devtoolsEventClient } from '@tanstack/devtools-client'\nimport chalk from 'chalk'\nimport { readPackageJson, tryParseJson } from './utils'\nimport { injectPluginIntoFile } from './inject-plugin'\nimport type { OutdatedDeps } from '@tanstack/devtools-client'\n\n/**\n * Gets the outdated command for the detected package manager\n */\nconst getOutdatedCommand = (packageManager: string): string => {\n switch (packageManager) {\n case 'yarn':\n return 'yarn outdated --json'\n case 'pnpm':\n return 'pnpm outdated --format json'\n case 'bun':\n return 'bun outdated --json'\n case 'npm':\n default:\n return 'npm outdated --json'\n }\n}\n\n/**\n * Adds a plugin to the devtools configuration file\n */\nexport const addPluginToDevtools = (\n devtoolsFileId: string | null,\n packageName: string,\n pluginName: string,\n pluginImport?: { importName: string; type: 'jsx' | 'function' },\n): { success: boolean; error?: string } => {\n // Check if we found the devtools file\n if (!devtoolsFileId) {\n const error = 'Devtools file not found'\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Could not add plugin. ${error}.`,\n ),\n )\n return { success: false, error }\n }\n\n // Inject the plugin into the file\n const result = injectPluginIntoFile(devtoolsFileId, {\n packageName,\n pluginName,\n pluginImport,\n })\n\n if (result.success) {\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully added ${packageName} to devtools!`,\n ),\n )\n } else {\n console.log(\n chalk.yellowBright(\n `[@tanstack/devtools-vite] Could not add plugin: ${result.error}`,\n ),\n )\n }\n\n return result\n}\n/**\n * Gets the install command for the detected package manager\n */\nconst getInstallCommand = (\n packageManager: string,\n packageName: string,\n): string => {\n switch (packageManager) {\n case 'yarn':\n return `yarn add -D ${packageName}`\n case 'pnpm':\n return `pnpm add -D ${packageName}`\n case 'bun':\n return `bun add -D ${packageName}`\n case 'npm':\n default:\n return `npm install -D ${packageName}`\n }\n}\n\nexport const installPackage = async (\n packageName: string,\n): Promise<{\n success: boolean\n error?: string\n}> => {\n return new Promise((resolve) => {\n const packageManager = detectPackageManager()\n const installCommand = getInstallCommand(packageManager, packageName)\n\n console.log(\n chalk.blueBright(\n `[@tanstack/devtools-vite] Installing ${packageName}...`,\n ),\n )\n\n exec(installCommand, async (installError) => {\n if (installError) {\n console.error(\n chalk.redBright(\n `[@tanstack/devtools-vite] Failed to install ${packageName}:`,\n ),\n installError.message,\n )\n resolve({\n success: false,\n error: installError.message,\n })\n return\n }\n\n console.log(\n chalk.greenBright(\n `[@tanstack/devtools-vite] Successfully installed ${packageName}`,\n ),\n )\n\n // Read the updated package.json and emit the event\n const updatedPackageJson = await readPackageJson()\n devtoolsEventClient.emit('package-json-updated', {\n packageJson: updatedPackageJson,\n })\n\n resolve({ success: true })\n })\n })\n}\n\n/**\n * Detects the package manager used in the project by checking for lock files\n */\nconst detectPackageManager = (): 'npm' | 'yarn' | 'pnpm' | 'bun' => {\n const cwd = process.cwd()\n\n // Check for lock files in order of specificity\n if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) {\n return 'bun'\n }\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm'\n }\n if (existsSync(join(cwd, 'yarn.lock'))) {\n return 'yarn'\n }\n if (existsSync(join(cwd, 'package-lock.json'))) {\n return 'npm'\n }\n\n // Default to pnpm if no lock file is found\n return 'pnpm'\n}\n\nexport const emitOutdatedDeps = async () => {\n return await new Promise<OutdatedDeps | null>((resolve) => {\n const packageManager = detectPackageManager()\n const outdatedCommand = getOutdatedCommand(packageManager)\n\n exec(outdatedCommand, (_, stdout) => {\n // outdated commands exit with code 1 if there are outdated packages, but still output valid JSON\n if (stdout) {\n const newOutdatedDeps = tryParseJson<OutdatedDeps>(stdout)\n if (!newOutdatedDeps) {\n return\n }\n devtoolsEventClient.emit('outdated-deps-read', {\n outdatedDeps: newOutdatedDeps,\n })\n resolve(newOutdatedDeps)\n }\n })\n })\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/plugin.js
CHANGED
|
@@ -1,30 +1,15 @@
|
|
|
1
|
-
import { exec } from "node:child_process";
|
|
2
1
|
import { devtoolsEventClient } from "@tanstack/devtools-client";
|
|
3
2
|
import { ServerEventBus } from "@tanstack/devtools-event-bus/server";
|
|
4
3
|
import { normalizePath } from "vite";
|
|
5
4
|
import chalk from "chalk";
|
|
6
|
-
import { handleDevToolsViteRequest, readPackageJson
|
|
5
|
+
import { handleDevToolsViteRequest, readPackageJson } from "./utils.js";
|
|
7
6
|
import { DEFAULT_EDITOR_CONFIG, handleOpenSource } from "./editor.js";
|
|
8
7
|
import { removeDevtools } from "./remove-devtools.js";
|
|
9
8
|
import { addSourceToJsx } from "./inject-source.js";
|
|
10
9
|
import { enhanceConsoleLog } from "./enhance-logs.js";
|
|
10
|
+
import { detectDevtoolsFile, injectPluginIntoFile } from "./inject-plugin.js";
|
|
11
|
+
import { emitOutdatedDeps, installPackage, addPluginToDevtools } from "./package-manager.js";
|
|
11
12
|
const defineDevtoolsConfig = (config) => config;
|
|
12
|
-
const emitOutdatedDeps = async () => {
|
|
13
|
-
return await new Promise((resolve) => {
|
|
14
|
-
exec("npm outdated --json", (_, stdout) => {
|
|
15
|
-
if (stdout) {
|
|
16
|
-
const newOutdatedDeps = tryParseJson(stdout);
|
|
17
|
-
if (!newOutdatedDeps) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
devtoolsEventClient.emit("outdated-deps-read", {
|
|
21
|
-
outdatedDeps: newOutdatedDeps
|
|
22
|
-
});
|
|
23
|
-
resolve(newOutdatedDeps);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
13
|
const devtools = (args) => {
|
|
29
14
|
let port = 5173;
|
|
30
15
|
const logging = args?.logging ?? true;
|
|
@@ -33,6 +18,7 @@ const devtools = (args) => {
|
|
|
33
18
|
const removeDevtoolsOnBuild = args?.removeDevtoolsOnBuild ?? true;
|
|
34
19
|
const serverBusEnabled = args?.eventBusConfig?.enabled ?? true;
|
|
35
20
|
const bus = new ServerEventBus(args?.eventBusConfig);
|
|
21
|
+
let devtoolsFileId = null;
|
|
36
22
|
return [
|
|
37
23
|
{
|
|
38
24
|
enforce: "pre",
|
|
@@ -129,6 +115,139 @@ ${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${
|
|
|
129
115
|
async configureServer() {
|
|
130
116
|
const packageJson = await readPackageJson();
|
|
131
117
|
const outdatedDeps = emitOutdatedDeps().then((deps) => deps);
|
|
118
|
+
devtoolsEventClient.on("install-devtools", async (event) => {
|
|
119
|
+
const result = await installPackage(event.payload.packageName);
|
|
120
|
+
devtoolsEventClient.emit("devtools-installed", {
|
|
121
|
+
packageName: event.payload.packageName,
|
|
122
|
+
success: result.success,
|
|
123
|
+
error: result.error
|
|
124
|
+
});
|
|
125
|
+
if (result.success) {
|
|
126
|
+
const { packageName, pluginName, pluginImport } = event.payload;
|
|
127
|
+
console.log(
|
|
128
|
+
chalk.blueBright(
|
|
129
|
+
`[@tanstack/devtools-vite] Auto-adding ${packageName} to devtools...`
|
|
130
|
+
)
|
|
131
|
+
);
|
|
132
|
+
const injectResult = addPluginToDevtools(
|
|
133
|
+
devtoolsFileId,
|
|
134
|
+
packageName,
|
|
135
|
+
pluginName,
|
|
136
|
+
pluginImport
|
|
137
|
+
);
|
|
138
|
+
if (injectResult.success) {
|
|
139
|
+
devtoolsEventClient.emit("plugin-added", {
|
|
140
|
+
packageName,
|
|
141
|
+
success: true
|
|
142
|
+
});
|
|
143
|
+
const updatedPackageJson = await readPackageJson();
|
|
144
|
+
devtoolsEventClient.emit("package-json-read", {
|
|
145
|
+
packageJson: updatedPackageJson
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
devtoolsEventClient.on("add-plugin-to-devtools", (event) => {
|
|
151
|
+
const { packageName, pluginName, pluginImport } = event.payload;
|
|
152
|
+
console.log(
|
|
153
|
+
chalk.blueBright(
|
|
154
|
+
`[@tanstack/devtools-vite] Adding ${packageName} to devtools...`
|
|
155
|
+
)
|
|
156
|
+
);
|
|
157
|
+
const result = addPluginToDevtools(
|
|
158
|
+
devtoolsFileId,
|
|
159
|
+
packageName,
|
|
160
|
+
pluginName,
|
|
161
|
+
pluginImport
|
|
162
|
+
);
|
|
163
|
+
devtoolsEventClient.emit("plugin-added", {
|
|
164
|
+
packageName,
|
|
165
|
+
success: result.success,
|
|
166
|
+
error: result.error
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
devtoolsEventClient.on("bump-package-version", async (event) => {
|
|
170
|
+
const {
|
|
171
|
+
packageName,
|
|
172
|
+
devtoolsPackage,
|
|
173
|
+
pluginName,
|
|
174
|
+
minVersion,
|
|
175
|
+
pluginImport
|
|
176
|
+
} = event.payload;
|
|
177
|
+
console.log(
|
|
178
|
+
chalk.blueBright(
|
|
179
|
+
`[@tanstack/devtools-vite] Bumping ${packageName} to version ${minVersion}...`
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
const packageWithVersion = minVersion ? `${packageName}@^${minVersion}` : packageName;
|
|
183
|
+
const result = await installPackage(packageWithVersion);
|
|
184
|
+
if (!result.success) {
|
|
185
|
+
console.log(
|
|
186
|
+
chalk.redBright(
|
|
187
|
+
`[@tanstack/devtools-vite] Failed to bump ${packageName}: ${result.error}`
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
devtoolsEventClient.emit("devtools-installed", {
|
|
191
|
+
packageName: devtoolsPackage,
|
|
192
|
+
success: false,
|
|
193
|
+
error: result.error
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
console.log(
|
|
198
|
+
chalk.greenBright(
|
|
199
|
+
`[@tanstack/devtools-vite] Successfully bumped ${packageName} to ${minVersion}!`
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
if (!devtoolsFileId) {
|
|
203
|
+
console.log(
|
|
204
|
+
chalk.yellowBright(
|
|
205
|
+
`[@tanstack/devtools-vite] Devtools file not found. Skipping auto-injection.`
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
devtoolsEventClient.emit("devtools-installed", {
|
|
209
|
+
packageName: devtoolsPackage,
|
|
210
|
+
success: true
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
console.log(
|
|
215
|
+
chalk.blueBright(
|
|
216
|
+
`[@tanstack/devtools-vite] Adding ${devtoolsPackage} to devtools...`
|
|
217
|
+
)
|
|
218
|
+
);
|
|
219
|
+
const injectResult = injectPluginIntoFile(devtoolsFileId, {
|
|
220
|
+
packageName: devtoolsPackage,
|
|
221
|
+
pluginName,
|
|
222
|
+
pluginImport
|
|
223
|
+
});
|
|
224
|
+
if (injectResult.success) {
|
|
225
|
+
console.log(
|
|
226
|
+
chalk.greenBright(
|
|
227
|
+
`[@tanstack/devtools-vite] Successfully added ${devtoolsPackage} to devtools!`
|
|
228
|
+
)
|
|
229
|
+
);
|
|
230
|
+
devtoolsEventClient.emit("plugin-added", {
|
|
231
|
+
packageName: devtoolsPackage,
|
|
232
|
+
success: true
|
|
233
|
+
});
|
|
234
|
+
const updatedPackageJson = await readPackageJson();
|
|
235
|
+
devtoolsEventClient.emit("package-json-read", {
|
|
236
|
+
packageJson: updatedPackageJson
|
|
237
|
+
});
|
|
238
|
+
} else {
|
|
239
|
+
console.log(
|
|
240
|
+
chalk.redBright(
|
|
241
|
+
`[@tanstack/devtools-vite] Failed to add ${devtoolsPackage} to devtools: ${injectResult.error}`
|
|
242
|
+
)
|
|
243
|
+
);
|
|
244
|
+
devtoolsEventClient.emit("plugin-added", {
|
|
245
|
+
packageName: devtoolsPackage,
|
|
246
|
+
success: false,
|
|
247
|
+
error: injectResult.error
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
132
251
|
devtoolsEventClient.on("mounted", async () => {
|
|
133
252
|
devtoolsEventClient.emit("outdated-deps-read", {
|
|
134
253
|
outdatedDeps: await outdatedDeps
|
|
@@ -159,6 +278,21 @@ ${chalk.greenBright(`[@tanstack/devtools-vite]`)} Removed devtools code from: ${
|
|
|
159
278
|
return;
|
|
160
279
|
return enhanceConsoleLog(code, id, port);
|
|
161
280
|
}
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "@tanstack/devtools:inject-plugin",
|
|
284
|
+
apply(config, { command }) {
|
|
285
|
+
return config.mode === "development" && command === "serve";
|
|
286
|
+
},
|
|
287
|
+
transform(code, id) {
|
|
288
|
+
if (!devtoolsFileId && detectDevtoolsFile(code)) {
|
|
289
|
+
const [filePath] = id.split("?");
|
|
290
|
+
if (filePath) {
|
|
291
|
+
devtoolsFileId = filePath;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return void 0;
|
|
295
|
+
}
|
|
162
296
|
}
|
|
163
297
|
];
|
|
164
298
|
};
|