@react-grab/cli 0.0.69 → 0.0.71

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.
Files changed (3) hide show
  1. package/dist/cli.cjs +453 -76
  2. package/dist/cli.js +455 -78
  3. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -80,22 +80,165 @@ var detectMonorepo = (projectRoot) => {
80
80
  }
81
81
  return false;
82
82
  };
83
- var detectReactGrab = (projectRoot) => {
83
+ var getWorkspacePatterns = (projectRoot) => {
84
+ const patterns = [];
85
+ const pnpmWorkspacePath = path.join(projectRoot, "pnpm-workspace.yaml");
86
+ if (fs.existsSync(pnpmWorkspacePath)) {
87
+ const content = fs.readFileSync(pnpmWorkspacePath, "utf-8");
88
+ const lines = content.split("\n");
89
+ let inPackages = false;
90
+ for (const line of lines) {
91
+ if (line.match(/^packages:\s*$/)) {
92
+ inPackages = true;
93
+ continue;
94
+ }
95
+ if (inPackages) {
96
+ if (line.match(/^[a-zA-Z]/) || line.trim() === "") {
97
+ if (line.match(/^[a-zA-Z]/)) inPackages = false;
98
+ continue;
99
+ }
100
+ const match = line.match(/^\s*-\s*['"]?([^'"#\n]+?)['"]?\s*$/);
101
+ if (match) {
102
+ patterns.push(match[1].trim());
103
+ }
104
+ }
105
+ }
106
+ }
107
+ const lernaJsonPath = path.join(projectRoot, "lerna.json");
108
+ if (fs.existsSync(lernaJsonPath)) {
109
+ try {
110
+ const lernaJson = JSON.parse(fs.readFileSync(lernaJsonPath, "utf-8"));
111
+ if (Array.isArray(lernaJson.packages)) {
112
+ patterns.push(...lernaJson.packages);
113
+ }
114
+ } catch {
115
+ }
116
+ }
84
117
  const packageJsonPath = path.join(projectRoot, "package.json");
85
- if (!fs.existsSync(packageJsonPath)) {
86
- return false;
118
+ if (fs.existsSync(packageJsonPath)) {
119
+ try {
120
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
121
+ if (Array.isArray(packageJson.workspaces)) {
122
+ patterns.push(...packageJson.workspaces);
123
+ } else if (packageJson.workspaces?.packages) {
124
+ patterns.push(...packageJson.workspaces.packages);
125
+ }
126
+ } catch {
127
+ }
87
128
  }
129
+ return [...new Set(patterns)];
130
+ };
131
+ var expandWorkspacePattern = (projectRoot, pattern) => {
132
+ const results = [];
133
+ const cleanPattern = pattern.replace(/\/\*$/, "");
134
+ const basePath = path.join(projectRoot, cleanPattern);
135
+ if (!fs.existsSync(basePath)) return results;
136
+ try {
137
+ const entries = fs.readdirSync(basePath, { withFileTypes: true });
138
+ for (const entry of entries) {
139
+ if (entry.isDirectory()) {
140
+ const packageJsonPath = path.join(basePath, entry.name, "package.json");
141
+ if (fs.existsSync(packageJsonPath)) {
142
+ results.push(path.join(basePath, entry.name));
143
+ }
144
+ }
145
+ }
146
+ } catch {
147
+ return results;
148
+ }
149
+ return results;
150
+ };
151
+ var hasReactDependency = (projectPath) => {
152
+ const packageJsonPath = path.join(projectPath, "package.json");
153
+ if (!fs.existsSync(packageJsonPath)) return false;
88
154
  try {
89
155
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
90
- const allDependencies = {
91
- ...packageJson.dependencies,
92
- ...packageJson.devDependencies
93
- };
94
- return Boolean(allDependencies["react-grab"]);
156
+ const allDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
157
+ return Boolean(allDeps["react"] || allDeps["react-dom"]);
95
158
  } catch {
96
159
  return false;
97
160
  }
98
161
  };
162
+ var findWorkspaceProjects = (projectRoot) => {
163
+ const patterns = getWorkspacePatterns(projectRoot);
164
+ const projects = [];
165
+ for (const pattern of patterns) {
166
+ const projectPaths = expandWorkspacePattern(projectRoot, pattern);
167
+ for (const projectPath of projectPaths) {
168
+ const framework = detectFramework(projectPath);
169
+ const hasReact = hasReactDependency(projectPath);
170
+ if (hasReact || framework !== "unknown") {
171
+ const packageJsonPath = path.join(projectPath, "package.json");
172
+ let name = path.basename(projectPath);
173
+ try {
174
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
175
+ name = packageJson.name || name;
176
+ } catch {
177
+ }
178
+ projects.push({
179
+ name,
180
+ path: projectPath,
181
+ framework,
182
+ hasReact
183
+ });
184
+ }
185
+ }
186
+ }
187
+ return projects;
188
+ };
189
+ var hasReactGrabInFile = (filePath) => {
190
+ if (!fs.existsSync(filePath)) return false;
191
+ try {
192
+ const content = fs.readFileSync(filePath, "utf-8");
193
+ const fuzzyPatterns = [
194
+ /["'`][^"'`]*react-grab/,
195
+ /react-grab[^"'`]*["'`]/,
196
+ /<[^>]*react-grab/i,
197
+ /import[^;]*react-grab/i,
198
+ /require[^)]*react-grab/i,
199
+ /from\s+[^;]*react-grab/i,
200
+ /src[^>]*react-grab/i
201
+ ];
202
+ return fuzzyPatterns.some((pattern) => pattern.test(content));
203
+ } catch {
204
+ return false;
205
+ }
206
+ };
207
+ var detectReactGrab = (projectRoot) => {
208
+ const packageJsonPath = path.join(projectRoot, "package.json");
209
+ if (fs.existsSync(packageJsonPath)) {
210
+ try {
211
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
212
+ const allDependencies = {
213
+ ...packageJson.dependencies,
214
+ ...packageJson.devDependencies
215
+ };
216
+ if (allDependencies["react-grab"]) {
217
+ return true;
218
+ }
219
+ } catch {
220
+ }
221
+ }
222
+ const filesToCheck = [
223
+ path.join(projectRoot, "app", "layout.tsx"),
224
+ path.join(projectRoot, "app", "layout.jsx"),
225
+ path.join(projectRoot, "src", "app", "layout.tsx"),
226
+ path.join(projectRoot, "src", "app", "layout.jsx"),
227
+ path.join(projectRoot, "pages", "_document.tsx"),
228
+ path.join(projectRoot, "pages", "_document.jsx"),
229
+ path.join(projectRoot, "instrumentation-client.ts"),
230
+ path.join(projectRoot, "instrumentation-client.js"),
231
+ path.join(projectRoot, "src", "instrumentation-client.ts"),
232
+ path.join(projectRoot, "src", "instrumentation-client.js"),
233
+ path.join(projectRoot, "index.html"),
234
+ path.join(projectRoot, "public", "index.html"),
235
+ path.join(projectRoot, "src", "index.tsx"),
236
+ path.join(projectRoot, "src", "index.ts"),
237
+ path.join(projectRoot, "src", "main.tsx"),
238
+ path.join(projectRoot, "src", "main.ts")
239
+ ];
240
+ return filesToCheck.some(hasReactGrabInFile);
241
+ };
99
242
  var AGENT_PACKAGES = ["@react-grab/claude-code", "@react-grab/cursor", "@react-grab/opencode"];
100
243
  var detectUnsupportedFramework = (projectRoot) => {
101
244
  const packageJsonPath = path.join(projectRoot, "package.json");
@@ -350,6 +493,19 @@ var WEBPACK_IMPORT_WITH_AGENT = (agent) => {
350
493
  var SCRIPT_IMPORT = 'import Script from "next/script";';
351
494
 
352
495
  // src/transform.ts
496
+ var hasReactGrabCode = (content) => {
497
+ const fuzzyPatterns = [
498
+ /["'`][^"'`]*react-grab/,
499
+ /react-grab[^"'`]*["'`]/,
500
+ /<[^>]*react-grab/i,
501
+ /import[^;]*react-grab/i,
502
+ /require[^)]*react-grab/i,
503
+ /from\s+[^;]*react-grab/i,
504
+ /src[^>]*react-grab/i,
505
+ /href[^>]*react-grab/i
506
+ ];
507
+ return fuzzyPatterns.some((pattern) => pattern.test(content));
508
+ };
353
509
  var findLayoutFile = (projectRoot) => {
354
510
  const possiblePaths = [
355
511
  path.join(projectRoot, "app", "layout.tsx"),
@@ -364,6 +520,26 @@ var findLayoutFile = (projectRoot) => {
364
520
  }
365
521
  return null;
366
522
  };
523
+ var findInstrumentationFile = (projectRoot) => {
524
+ const possiblePaths = [
525
+ path.join(projectRoot, "instrumentation-client.ts"),
526
+ path.join(projectRoot, "instrumentation-client.js"),
527
+ path.join(projectRoot, "src", "instrumentation-client.ts"),
528
+ path.join(projectRoot, "src", "instrumentation-client.js")
529
+ ];
530
+ for (const filePath of possiblePaths) {
531
+ if (fs.existsSync(filePath)) {
532
+ return filePath;
533
+ }
534
+ }
535
+ return null;
536
+ };
537
+ var hasReactGrabInInstrumentation = (projectRoot) => {
538
+ const instrumentationPath = findInstrumentationFile(projectRoot);
539
+ if (!instrumentationPath) return false;
540
+ const content = fs.readFileSync(instrumentationPath, "utf-8");
541
+ return hasReactGrabCode(content);
542
+ };
367
543
  var findDocumentFile = (projectRoot) => {
368
544
  const possiblePaths = [
369
545
  path.join(projectRoot, "pages", "_document.tsx"),
@@ -431,7 +607,7 @@ var addAgentToExistingNextApp = (originalContent, agent, filePath) => {
431
607
  strategy="lazyOnload"
432
608
  />`;
433
609
  const reactGrabScriptMatch = originalContent.match(
434
- /<Script[^>]*src="[^"]*react-grab[^"]*"[^>]*\/?>/
610
+ /<(?:Script|script|NextScript)[^>]*react-grab[^>]*\/?>/is
435
611
  );
436
612
  if (reactGrabScriptMatch) {
437
613
  const newContent = originalContent.replace(
@@ -544,15 +720,16 @@ var transformNextAppRouter = (projectRoot, agent, reactGrabAlreadyConfigured) =>
544
720
  }
545
721
  const originalContent = fs.readFileSync(layoutPath, "utf-8");
546
722
  let newContent = originalContent;
547
- const hasReactGrabInFile = originalContent.includes("react-grab");
548
- if (hasReactGrabInFile && reactGrabAlreadyConfigured) {
723
+ const hasReactGrabInFile2 = hasReactGrabCode(originalContent);
724
+ const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
725
+ if (hasReactGrabInFile2 && reactGrabAlreadyConfigured) {
549
726
  return addAgentToExistingNextApp(originalContent, agent, layoutPath);
550
727
  }
551
- if (hasReactGrabInFile) {
728
+ if (hasReactGrabInFile2 || hasReactGrabInInstrumentationFile) {
552
729
  return {
553
730
  success: true,
554
731
  filePath: layoutPath,
555
- message: "React Grab is already installed in this file",
732
+ message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
556
733
  noChanges: true
557
734
  };
558
735
  }
@@ -603,15 +780,16 @@ var transformNextPagesRouter = (projectRoot, agent, reactGrabAlreadyConfigured)
603
780
  }
604
781
  const originalContent = fs.readFileSync(documentPath, "utf-8");
605
782
  let newContent = originalContent;
606
- const hasReactGrabInFile = originalContent.includes("react-grab");
607
- if (hasReactGrabInFile && reactGrabAlreadyConfigured) {
783
+ const hasReactGrabInFile2 = hasReactGrabCode(originalContent);
784
+ const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
785
+ if (hasReactGrabInFile2 && reactGrabAlreadyConfigured) {
608
786
  return addAgentToExistingNextApp(originalContent, agent, documentPath);
609
787
  }
610
- if (hasReactGrabInFile) {
788
+ if (hasReactGrabInFile2 || hasReactGrabInInstrumentationFile) {
611
789
  return {
612
790
  success: true,
613
791
  filePath: documentPath,
614
- message: "React Grab is already installed in this file",
792
+ message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
615
793
  noChanges: true
616
794
  };
617
795
  }
@@ -647,11 +825,11 @@ var transformVite = (projectRoot, agent, reactGrabAlreadyConfigured) => {
647
825
  }
648
826
  const originalContent = fs.readFileSync(indexPath, "utf-8");
649
827
  let newContent = originalContent;
650
- const hasReactGrabInFile = originalContent.includes("react-grab");
651
- if (hasReactGrabInFile && reactGrabAlreadyConfigured) {
828
+ const hasReactGrabInFile2 = hasReactGrabCode(originalContent);
829
+ if (hasReactGrabInFile2 && reactGrabAlreadyConfigured) {
652
830
  return addAgentToExistingVite(originalContent, agent, indexPath);
653
831
  }
654
- if (hasReactGrabInFile) {
832
+ if (hasReactGrabInFile2) {
655
833
  return {
656
834
  success: true,
657
835
  filePath: indexPath,
@@ -683,11 +861,11 @@ var transformWebpack = (projectRoot, agent, reactGrabAlreadyConfigured) => {
683
861
  };
684
862
  }
685
863
  const originalContent = fs.readFileSync(entryPath, "utf-8");
686
- const hasReactGrabInFile = originalContent.includes("react-grab");
687
- if (hasReactGrabInFile && reactGrabAlreadyConfigured) {
864
+ const hasReactGrabInFile2 = hasReactGrabCode(originalContent);
865
+ if (hasReactGrabInFile2 && reactGrabAlreadyConfigured) {
688
866
  return addAgentToExistingWebpack(originalContent, agent, entryPath);
689
867
  }
690
- if (hasReactGrabInFile) {
868
+ if (hasReactGrabInFile2) {
691
869
  return {
692
870
  success: true,
693
871
  filePath: entryPath,
@@ -853,7 +1031,25 @@ var applyPackageJsonTransform = (result) => {
853
1031
  };
854
1032
 
855
1033
  // src/cli.ts
856
- var VERSION = "0.0.68";
1034
+ var VERSION = "0.0.71";
1035
+ var REPORT_URL = "https://reactgrab.com/api/report-cli";
1036
+ var reportToCli = async (type, config, error) => {
1037
+ try {
1038
+ await fetch(REPORT_URL, {
1039
+ method: "POST",
1040
+ headers: { "Content-Type": "application/json" },
1041
+ body: JSON.stringify({
1042
+ type,
1043
+ version: VERSION,
1044
+ config,
1045
+ error: error ? { message: error.message, stack: error.stack } : void 0,
1046
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1047
+ })
1048
+ }).catch(() => {
1049
+ });
1050
+ } catch {
1051
+ }
1052
+ };
857
1053
  var FRAMEWORK_NAMES = {
858
1054
  next: "Next.js",
859
1055
  vite: "Vite",
@@ -884,49 +1080,122 @@ var showDocsLink = () => {
884
1080
  `);
885
1081
  };
886
1082
  var showManualInstructions = (framework, nextRouterType) => {
887
- console.log(`
1083
+ console.log(
1084
+ `
888
1085
  ${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Manual Setup Instructions:")}
889
- `);
1086
+ `
1087
+ );
890
1088
  if (framework === "next" && nextRouterType === "app") {
891
1089
  console.log(`${pc__default.default.bold("Next.js App Router:")}`);
892
1090
  console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
893
- console.log(` 2. Add to ${pc__default.default.cyan("app/layout.tsx")}:`);
1091
+ console.log(` 2. Add to ${pc__default.default.cyan("app/layout.tsx")} inside <head>:`);
894
1092
  console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
895
- console.log(` ${pc__default.default.gray("// Inside <head> or after <html>:")}`);
896
- console.log(` ${pc__default.default.gray('<Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`);
1093
+ console.log(
1094
+ ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1095
+ );
1096
+ console.log(` ${pc__default.default.gray(" <Script")}`);
1097
+ console.log(
1098
+ ` ${pc__default.default.gray(' src="//unpkg.com/react-grab/dist/index.global.js"')}`
1099
+ );
1100
+ console.log(` ${pc__default.default.gray(' crossOrigin="anonymous"')}`);
1101
+ console.log(` ${pc__default.default.gray(' strategy="beforeInteractive"')}`);
1102
+ console.log(` ${pc__default.default.gray(" />")}`);
1103
+ console.log(` ${pc__default.default.gray(")}")}`);
897
1104
  } else if (framework === "next" && nextRouterType === "pages") {
898
1105
  console.log(`${pc__default.default.bold("Next.js Pages Router:")}`);
899
1106
  console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
900
- console.log(` 2. Create or edit ${pc__default.default.cyan("pages/_document.tsx")}:`);
1107
+ console.log(` 2. Add to ${pc__default.default.cyan("pages/_document.tsx")} inside <Head>:`);
901
1108
  console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
902
- console.log(` ${pc__default.default.gray("// Inside <Head>:")}`);
903
- console.log(` ${pc__default.default.gray('<Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`);
1109
+ console.log(
1110
+ ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1111
+ );
1112
+ console.log(` ${pc__default.default.gray(" <Script")}`);
1113
+ console.log(
1114
+ ` ${pc__default.default.gray(' src="//unpkg.com/react-grab/dist/index.global.js"')}`
1115
+ );
1116
+ console.log(` ${pc__default.default.gray(' crossOrigin="anonymous"')}`);
1117
+ console.log(` ${pc__default.default.gray(' strategy="beforeInteractive"')}`);
1118
+ console.log(` ${pc__default.default.gray(" />")}`);
1119
+ console.log(` ${pc__default.default.gray(")}")}`);
904
1120
  } else if (framework === "vite") {
905
1121
  console.log(`${pc__default.default.bold("Vite:")}`);
906
1122
  console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
907
1123
  console.log(` 2. Add to ${pc__default.default.cyan("index.html")} inside <head>:`);
908
1124
  console.log(` ${pc__default.default.gray('<script type="module">')}`);
909
- console.log(` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`);
1125
+ console.log(
1126
+ ` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`
1127
+ );
910
1128
  console.log(` ${pc__default.default.gray("</script>")}`);
911
1129
  } else if (framework === "webpack") {
912
1130
  console.log(`${pc__default.default.bold("Webpack:")}`);
913
1131
  console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
914
- console.log(` 2. Add to your entry file (e.g., ${pc__default.default.cyan("src/index.tsx")}):`);
915
- console.log(` ${pc__default.default.gray('if (process.env.NODE_ENV === "development") {')}`);
1132
+ console.log(
1133
+ ` 2. Add to your entry file (e.g., ${pc__default.default.cyan("src/index.tsx")}):`
1134
+ );
1135
+ console.log(
1136
+ ` ${pc__default.default.gray('if (process.env.NODE_ENV === "development") {')}`
1137
+ );
916
1138
  console.log(` ${pc__default.default.gray(' import("react-grab");')}`);
917
1139
  console.log(` ${pc__default.default.gray("}")}`);
918
1140
  } else {
919
- console.log(`${pc__default.default.bold("Generic Setup:")}`);
920
- console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
921
- console.log(` 2. Add the script to your HTML or entry file.`);
922
- console.log(` 3. See docs for framework-specific instructions.`);
1141
+ console.log(
1142
+ `${pc__default.default.bold("Next.js App Router:")} Add to ${pc__default.default.cyan("app/layout.tsx")} inside <head>:`
1143
+ );
1144
+ console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1145
+ console.log(
1146
+ ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1147
+ );
1148
+ console.log(
1149
+ ` ${pc__default.default.gray(' <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`
1150
+ );
1151
+ console.log(` ${pc__default.default.gray(")}")}`);
1152
+ console.log("");
1153
+ console.log(
1154
+ `${pc__default.default.bold("Next.js Pages Router:")} Add to ${pc__default.default.cyan("pages/_document.tsx")} inside <Head>:`
1155
+ );
1156
+ console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1157
+ console.log(
1158
+ ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1159
+ );
1160
+ console.log(
1161
+ ` ${pc__default.default.gray(' <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`
1162
+ );
1163
+ console.log(` ${pc__default.default.gray(")}")}`);
1164
+ console.log("");
1165
+ console.log(
1166
+ `${pc__default.default.bold("Vite:")} Add to ${pc__default.default.cyan("index.html")} inside <head>:`
1167
+ );
1168
+ console.log(` ${pc__default.default.gray('<script type="module">')}`);
1169
+ console.log(
1170
+ ` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`
1171
+ );
1172
+ console.log(` ${pc__default.default.gray("</script>")}`);
1173
+ console.log("");
1174
+ console.log(
1175
+ `${pc__default.default.bold("Webpack:")} Add to entry file (e.g., ${pc__default.default.cyan("src/index.tsx")}):`
1176
+ );
1177
+ console.log(
1178
+ ` ${pc__default.default.gray('if (process.env.NODE_ENV === "development") {')}`
1179
+ );
1180
+ console.log(` ${pc__default.default.gray(' import("react-grab");')}`);
1181
+ console.log(` ${pc__default.default.gray("}")}`);
1182
+ console.log("");
1183
+ console.log(`For full instructions, visit:`);
1184
+ console.log(
1185
+ ` ${pc__default.default.cyan("https://github.com/aidenybai/react-grab#readme")}`
1186
+ );
1187
+ return;
923
1188
  }
924
1189
  showDocsLink();
925
1190
  };
926
1191
  var showAccuracyWarning = () => {
927
- console.log(`
928
- ${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Auto-detection may not be 100% accurate.")}`);
929
- console.log(`${pc__default.default.yellow(" Please verify the changes in your file before committing.")}`);
1192
+ console.log(
1193
+ `
1194
+ ${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Auto-detection may not be 100% accurate.")}`
1195
+ );
1196
+ console.log(
1197
+ `${pc__default.default.yellow(" Please verify the changes in your file before committing.")}`
1198
+ );
930
1199
  };
931
1200
  var parseArgs = async () => {
932
1201
  const argv = await yargs__default.default(helpers.hideBin(process.argv)).scriptName("react-grab").usage(
@@ -968,7 +1237,13 @@ router type) and installs React Grab with optional agent integrations.`
968
1237
  type: "boolean",
969
1238
  default: false,
970
1239
  description: "Only modify config files, skip npm/yarn/pnpm install"
971
- }).help().alias("help", "h").version(VERSION).alias("version", "v").example("$0", "Run interactive setup with prompts").example("$0 -y", "Auto-detect everything and install without prompts").example("$0 -f next -r app", "Configure for Next.js App Router").example("$0 -a cursor -y", "Add Cursor agent integration non-interactively").example("$0 -p pnpm -a claude-code", "Use pnpm and add Claude Code agent").example("$0 --skip-install", "Only modify files, install packages manually").epilog(
1240
+ }).help().alias("help", "h").version(VERSION).alias("version", "v").example("$0", "Run interactive setup with prompts").example("$0 -y", "Auto-detect everything and install without prompts").example("$0 -f next -r app", "Configure for Next.js App Router").example(
1241
+ "$0 -a cursor -y",
1242
+ "Add Cursor agent integration non-interactively"
1243
+ ).example("$0 -p pnpm -a claude-code", "Use pnpm and add Claude Code agent").example(
1244
+ "$0 --skip-install",
1245
+ "Only modify files, install packages manually"
1246
+ ).epilog(
972
1247
  `${pc__default.default.bold("Agent Integrations:")}
973
1248
  ${pc__default.default.cyan("claude-code")} Connect React Grab to Claude Code
974
1249
  ${pc__default.default.cyan("cursor")} Connect React Grab to Cursor IDE
@@ -993,33 +1268,104 @@ ${pc__default.default.bold("Documentation:")} ${pc__default.default.underline(DO
993
1268
  var main = async () => {
994
1269
  const args = await parseArgs();
995
1270
  const isNonInteractive = args.yes;
996
- console.log(`
997
- ${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)}`);
1271
+ console.log(
1272
+ `
1273
+ ${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)}`
1274
+ );
998
1275
  const projectInfo = await detectProject(process.cwd());
999
- console.log(`- Framework: ${pc__default.default.cyan(FRAMEWORK_NAMES[projectInfo.framework])}`);
1000
- console.log(`- Package Manager: ${pc__default.default.cyan(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}`);
1276
+ console.log(
1277
+ `- Framework: ${pc__default.default.cyan(FRAMEWORK_NAMES[projectInfo.framework])}`
1278
+ );
1279
+ console.log(
1280
+ `- Package Manager: ${pc__default.default.cyan(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}`
1281
+ );
1001
1282
  if (projectInfo.framework === "next") {
1002
- console.log(`- Router Type: ${pc__default.default.cyan(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`);
1283
+ console.log(
1284
+ `- Router Type: ${pc__default.default.cyan(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`
1285
+ );
1003
1286
  }
1004
- console.log(`- Monorepo: ${pc__default.default.cyan(projectInfo.isMonorepo ? "Yes" : "No")}`);
1005
- console.log(`- React Grab: ${projectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`);
1287
+ console.log(
1288
+ `- Monorepo: ${pc__default.default.cyan(projectInfo.isMonorepo ? "Yes" : "No")}`
1289
+ );
1290
+ console.log(
1291
+ `- React Grab: ${projectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`
1292
+ );
1006
1293
  if (projectInfo.installedAgents.length > 0) {
1007
- console.log(`- Agents: ${pc__default.default.cyan(projectInfo.installedAgents.map((agent) => AGENT_NAMES[agent] || agent).join(", "))}`);
1294
+ console.log(
1295
+ `- Agents: ${pc__default.default.cyan(projectInfo.installedAgents.map((agent) => AGENT_NAMES[agent] || agent).join(", "))}`
1296
+ );
1008
1297
  }
1009
1298
  console.log("");
1010
1299
  if (projectInfo.unsupportedFramework) {
1011
1300
  const frameworkName = UNSUPPORTED_FRAMEWORK_NAMES[projectInfo.unsupportedFramework];
1012
- console.log(`${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow(`Detected ${frameworkName} - this framework requires manual setup.`)}`);
1013
- console.log(`${pc__default.default.yellow(" React Grab may not work correctly with auto-configuration.")}
1014
- `);
1301
+ console.log(
1302
+ `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow(`Detected ${frameworkName} - this framework requires manual setup.`)}`
1303
+ );
1304
+ console.log(
1305
+ `${pc__default.default.yellow(" React Grab may not work correctly with auto-configuration.")}
1306
+ `
1307
+ );
1015
1308
  showManualInstructions(projectInfo.framework, projectInfo.nextRouterType);
1016
1309
  process.exit(0);
1017
1310
  }
1018
1311
  if (projectInfo.framework === "unknown") {
1019
- console.log(`${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Could not detect framework automatically.")}
1020
- `);
1021
- showManualInstructions("unknown");
1022
- process.exit(0);
1312
+ if (projectInfo.isMonorepo && !isNonInteractive) {
1313
+ const workspaceProjects = findWorkspaceProjects(projectInfo.projectRoot);
1314
+ const reactProjects = workspaceProjects.filter(
1315
+ (p) => p.hasReact || p.framework !== "unknown"
1316
+ );
1317
+ if (reactProjects.length > 0) {
1318
+ console.log(
1319
+ `${pc__default.default.cyan("\u2139")} ${pc__default.default.cyan("Found React projects in this monorepo:")}
1320
+ `
1321
+ );
1322
+ const selectedProject = await prompts.select({
1323
+ message: "Select a project to install React Grab:",
1324
+ choices: reactProjects.map((project) => ({
1325
+ name: `${project.name} ${pc__default.default.gray(`(${FRAMEWORK_NAMES[project.framework] || "React"})`)}`,
1326
+ value: project.path
1327
+ }))
1328
+ });
1329
+ console.log(
1330
+ `
1331
+ ${pc__default.default.magenta("\u269B")} Switching to ${pc__default.default.cyan(selectedProject)}...
1332
+ `
1333
+ );
1334
+ process.chdir(selectedProject);
1335
+ const newProjectInfo = await detectProject(selectedProject);
1336
+ projectInfo.framework = newProjectInfo.framework;
1337
+ projectInfo.nextRouterType = newProjectInfo.nextRouterType;
1338
+ projectInfo.hasReactGrab = newProjectInfo.hasReactGrab;
1339
+ projectInfo.installedAgents = newProjectInfo.installedAgents;
1340
+ projectInfo.projectRoot = newProjectInfo.projectRoot;
1341
+ console.log(
1342
+ `- Framework: ${pc__default.default.cyan(FRAMEWORK_NAMES[newProjectInfo.framework])}`
1343
+ );
1344
+ if (newProjectInfo.framework === "next") {
1345
+ console.log(
1346
+ `- Router Type: ${pc__default.default.cyan(newProjectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`
1347
+ );
1348
+ }
1349
+ console.log(
1350
+ `- React Grab: ${newProjectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`
1351
+ );
1352
+ console.log("");
1353
+ } else {
1354
+ console.log(
1355
+ `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Could not detect framework automatically.")}
1356
+ `
1357
+ );
1358
+ showManualInstructions("unknown");
1359
+ process.exit(0);
1360
+ }
1361
+ } else {
1362
+ console.log(
1363
+ `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Could not detect framework automatically.")}
1364
+ `
1365
+ );
1366
+ showManualInstructions("unknown");
1367
+ process.exit(0);
1368
+ }
1023
1369
  }
1024
1370
  let action = "install-all";
1025
1371
  if (projectInfo.hasReactGrab && !isNonInteractive) {
@@ -1034,9 +1380,13 @@ ${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab"
1034
1380
  } else if (projectInfo.hasReactGrab && args.agent && args.agent !== "none") {
1035
1381
  action = "add-agent";
1036
1382
  } else if (projectInfo.hasReactGrab && isNonInteractive && !args.agent) {
1037
- console.log(`${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("React Grab is already installed.")}`);
1038
- console.log(`${pc__default.default.yellow(" Use --agent to add an agent, or run without -y for interactive mode.")}
1039
- `);
1383
+ console.log(
1384
+ `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("React Grab is already installed.")}`
1385
+ );
1386
+ console.log(
1387
+ `${pc__default.default.yellow(" Use --agent to add an agent, or run without -y for interactive mode.")}
1388
+ `
1389
+ );
1040
1390
  action = "reconfigure";
1041
1391
  }
1042
1392
  let finalFramework = args.framework || projectInfo.framework;
@@ -1088,9 +1438,11 @@ ${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab"
1088
1438
  { name: "Opencode", value: "opencode" }
1089
1439
  ].filter((agent) => !projectInfo.installedAgents.includes(agent.value));
1090
1440
  if (availableAgents.length === 0) {
1091
- console.log(`
1441
+ console.log(
1442
+ `
1092
1443
  ${pc__default.default.green("All agent integrations are already installed.")}
1093
- `);
1444
+ `
1445
+ );
1094
1446
  } else if (action === "add-agent") {
1095
1447
  agentIntegration = await prompts.select({
1096
1448
  message: "Select an agent integration to add:",
@@ -1146,7 +1498,11 @@ ${pc__default.default.magenta("\u269B")} Previewing changes...
1146
1498
  if (hasLayoutChanges) {
1147
1499
  console.log("");
1148
1500
  }
1149
- printDiff(packageJsonResult.filePath, packageJsonResult.originalContent, packageJsonResult.newContent);
1501
+ printDiff(
1502
+ packageJsonResult.filePath,
1503
+ packageJsonResult.originalContent,
1504
+ packageJsonResult.newContent
1505
+ );
1150
1506
  }
1151
1507
  if (hasLayoutChanges || hasPackageJsonChanges) {
1152
1508
  showAccuracyWarning();
@@ -1163,16 +1519,25 @@ ${pc__default.default.yellow("Changes cancelled.")}
1163
1519
  }
1164
1520
  }
1165
1521
  }
1166
- const shouldInstallReactGrab = action === "install-all" && !projectInfo.hasReactGrab;
1522
+ const shouldInstallReactGrab = (action === "install-all" || action === "add-agent") && !projectInfo.hasReactGrab;
1167
1523
  const shouldInstallAgent = agentIntegration !== "none" && !projectInfo.installedAgents.includes(agentIntegration);
1168
1524
  if (!args.skipInstall && (shouldInstallReactGrab || shouldInstallAgent)) {
1169
- const packages = getPackagesToInstall(agentIntegration, shouldInstallReactGrab);
1525
+ const packages = getPackagesToInstall(
1526
+ agentIntegration,
1527
+ shouldInstallReactGrab
1528
+ );
1170
1529
  if (packages.length > 0) {
1171
- console.log(`
1530
+ console.log(
1531
+ `
1172
1532
  ${pc__default.default.magenta("\u269B")} Installing: ${pc__default.default.cyan(packages.join(", "))}
1173
- `);
1533
+ `
1534
+ );
1174
1535
  try {
1175
- installPackages(packages, finalPackageManager, projectInfo.projectRoot);
1536
+ installPackages(
1537
+ packages,
1538
+ finalPackageManager,
1539
+ projectInfo.projectRoot
1540
+ );
1176
1541
  console.log(`
1177
1542
  ${pc__default.default.green("Packages installed successfully!")}
1178
1543
  `);
@@ -1198,8 +1563,10 @@ ${pc__default.default.green("Applied:")} ${result.filePath}`);
1198
1563
  if (hasPackageJsonChanges) {
1199
1564
  const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
1200
1565
  if (!packageJsonWriteResult.success) {
1201
- console.error(`
1202
- ${pc__default.default.red("Error:")} ${packageJsonWriteResult.error}`);
1566
+ console.error(
1567
+ `
1568
+ ${pc__default.default.red("Error:")} ${packageJsonWriteResult.error}`
1569
+ );
1203
1570
  showDocsLink();
1204
1571
  process.exit(1);
1205
1572
  }
@@ -1211,20 +1578,30 @@ ${pc__default.default.red("Error:")} ${packageJsonWriteResult.error}`);
1211
1578
  ${pc__default.default.green("Done!")}`);
1212
1579
  console.log(`
1213
1580
  Next steps:`);
1214
- console.log(` - Start your development server`);
1215
- console.log(` - Select an element to copy its context`);
1216
- console.log(` - Learn more at ${pc__default.default.cyan(DOCS_URL)}
1581
+ console.log(`- Start your development server`);
1582
+ console.log(`- Select an element to copy its context`);
1583
+ console.log(`- Learn more at ${pc__default.default.cyan(DOCS_URL)}
1217
1584
  `);
1218
1585
  if (agentIntegration !== "none") {
1219
- console.log(`${pc__default.default.magenta("\u269B")} Agent: ${pc__default.default.cyan(AGENT_NAMES[agentIntegration])}`);
1586
+ console.log(
1587
+ `${pc__default.default.magenta("\u269B")} Agent: ${pc__default.default.cyan(AGENT_NAMES[agentIntegration])}`
1588
+ );
1220
1589
  console.log(` Make sure to start the agent server before using it.
1221
1590
  `);
1222
1591
  }
1592
+ await reportToCli("completed", {
1593
+ framework: finalFramework,
1594
+ packageManager: finalPackageManager,
1595
+ router: finalNextRouterType,
1596
+ agent: agentIntegration !== "none" ? agentIntegration : void 0,
1597
+ isMonorepo: projectInfo.isMonorepo
1598
+ });
1223
1599
  };
1224
- main().catch((error) => {
1600
+ main().catch(async (error) => {
1225
1601
  console.error(`${pc__default.default.red("Error:")}`, error);
1226
1602
  console.log("\nFor manual installation instructions, visit:");
1227
1603
  console.log(` ${DOCS_URL}
1228
1604
  `);
1605
+ await reportToCli("error", void 0, error);
1229
1606
  process.exit(1);
1230
1607
  });