@react-grab/cli 0.0.72 → 0.0.74
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/cli.cjs +470 -504
- package/dist/cli.js +469 -503
- package/package.json +6 -5
package/dist/cli.cjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var helpers = require('yargs/helpers');
|
|
4
|
+
var commander = require('commander');
|
|
5
|
+
var prompts2 = require('prompts');
|
|
6
|
+
var child_process = require('child_process');
|
|
8
7
|
var fs = require('fs');
|
|
9
8
|
var path = require('path');
|
|
10
9
|
var ni = require('@antfu/ni');
|
|
11
|
-
var
|
|
10
|
+
var colors = require('kleur/colors');
|
|
11
|
+
var ora = require('ora');
|
|
12
12
|
|
|
13
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
14
|
|
|
15
|
-
var
|
|
16
|
-
var
|
|
15
|
+
var prompts2__default = /*#__PURE__*/_interopDefault(prompts2);
|
|
16
|
+
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
17
17
|
|
|
18
18
|
var detectPackageManager = async (projectRoot) => {
|
|
19
19
|
const detected = await ni.detect({ cwd: projectRoot });
|
|
@@ -301,7 +301,7 @@ var detectProject = async (projectRoot = process.cwd()) => {
|
|
|
301
301
|
};
|
|
302
302
|
};
|
|
303
303
|
|
|
304
|
-
// src/diff.ts
|
|
304
|
+
// src/utils/diff.ts
|
|
305
305
|
var RED = "\x1B[31m";
|
|
306
306
|
var GREEN = "\x1B[32m";
|
|
307
307
|
var GRAY = "\x1B[90m";
|
|
@@ -388,6 +388,50 @@ ${BOLD}File: ${filePath}${RESET}`);
|
|
|
388
388
|
console.log(formatDiff(diff));
|
|
389
389
|
console.log("\u2500".repeat(60));
|
|
390
390
|
};
|
|
391
|
+
var highlighter = {
|
|
392
|
+
error: colors.red,
|
|
393
|
+
warn: colors.yellow,
|
|
394
|
+
info: colors.cyan,
|
|
395
|
+
success: colors.green,
|
|
396
|
+
dim: colors.dim
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// src/utils/logger.ts
|
|
400
|
+
var logger = {
|
|
401
|
+
error(...args) {
|
|
402
|
+
console.log(highlighter.error(args.join(" ")));
|
|
403
|
+
},
|
|
404
|
+
warn(...args) {
|
|
405
|
+
console.log(highlighter.warn(args.join(" ")));
|
|
406
|
+
},
|
|
407
|
+
info(...args) {
|
|
408
|
+
console.log(highlighter.info(args.join(" ")));
|
|
409
|
+
},
|
|
410
|
+
success(...args) {
|
|
411
|
+
console.log(highlighter.success(args.join(" ")));
|
|
412
|
+
},
|
|
413
|
+
log(...args) {
|
|
414
|
+
console.log(args.join(" "));
|
|
415
|
+
},
|
|
416
|
+
break() {
|
|
417
|
+
console.log("");
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/utils/handle-error.ts
|
|
422
|
+
var handleError = (error) => {
|
|
423
|
+
logger.break();
|
|
424
|
+
logger.error(
|
|
425
|
+
"Something went wrong. Please check the error below for more details."
|
|
426
|
+
);
|
|
427
|
+
logger.error("If the problem persists, please open an issue on GitHub.");
|
|
428
|
+
logger.error("");
|
|
429
|
+
if (error instanceof Error) {
|
|
430
|
+
logger.error(error.message);
|
|
431
|
+
}
|
|
432
|
+
logger.break();
|
|
433
|
+
process.exit(1);
|
|
434
|
+
};
|
|
391
435
|
var INSTALL_COMMANDS = {
|
|
392
436
|
npm: "npm install",
|
|
393
437
|
yarn: "yarn add",
|
|
@@ -418,8 +462,9 @@ var getPackagesToInstall = (agent, includeReactGrab = true) => {
|
|
|
418
462
|
}
|
|
419
463
|
return packages;
|
|
420
464
|
};
|
|
465
|
+
var spinner = (text, options) => ora__default.default({ text, isSilent: options?.silent, stream: process.stdout });
|
|
421
466
|
|
|
422
|
-
// src/templates.ts
|
|
467
|
+
// src/utils/templates.ts
|
|
423
468
|
var NEXT_APP_ROUTER_SCRIPT = `{process.env.NODE_ENV === "development" && (
|
|
424
469
|
<Script
|
|
425
470
|
src="//unpkg.com/react-grab/dist/index.global.js"
|
|
@@ -492,7 +537,7 @@ var WEBPACK_IMPORT_WITH_AGENT = (agent) => {
|
|
|
492
537
|
};
|
|
493
538
|
var SCRIPT_IMPORT = 'import Script from "next/script";';
|
|
494
539
|
|
|
495
|
-
// src/transform.ts
|
|
540
|
+
// src/utils/transform.ts
|
|
496
541
|
var hasReactGrabCode = (content) => {
|
|
497
542
|
const fuzzyPatterns = [
|
|
498
543
|
/["'`][^"'`]*react-grab/,
|
|
@@ -648,11 +693,13 @@ var addAgentToExistingVite = (originalContent, agent, filePath) => {
|
|
|
648
693
|
};
|
|
649
694
|
}
|
|
650
695
|
const agentImport = `import("${agentPackage}/client");`;
|
|
651
|
-
const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\)
|
|
696
|
+
const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\);?/);
|
|
652
697
|
if (reactGrabImportMatch) {
|
|
698
|
+
const matchedText = reactGrabImportMatch[0];
|
|
699
|
+
const hasSemicolon = matchedText.endsWith(";");
|
|
653
700
|
const newContent = originalContent.replace(
|
|
654
|
-
|
|
655
|
-
`${
|
|
701
|
+
matchedText,
|
|
702
|
+
`${hasSemicolon ? matchedText.slice(0, -1) : matchedText};
|
|
656
703
|
${agentImport}`
|
|
657
704
|
);
|
|
658
705
|
return {
|
|
@@ -688,11 +735,13 @@ var addAgentToExistingWebpack = (originalContent, agent, filePath) => {
|
|
|
688
735
|
};
|
|
689
736
|
}
|
|
690
737
|
const agentImport = `import("${agentPackage}/client");`;
|
|
691
|
-
const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\)
|
|
738
|
+
const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\);?/);
|
|
692
739
|
if (reactGrabImportMatch) {
|
|
740
|
+
const matchedText = reactGrabImportMatch[0];
|
|
741
|
+
const hasSemicolon = matchedText.endsWith(";");
|
|
693
742
|
const newContent = originalContent.replace(
|
|
694
|
-
|
|
695
|
-
`${
|
|
743
|
+
matchedText,
|
|
744
|
+
`${hasSemicolon ? matchedText.slice(0, -1) : matchedText};
|
|
696
745
|
${agentImport}`
|
|
697
746
|
);
|
|
698
747
|
return {
|
|
@@ -938,11 +987,11 @@ var AGENT_PREFIXES = {
|
|
|
938
987
|
opencode: "npx @react-grab/opencode@latest &&"
|
|
939
988
|
};
|
|
940
989
|
var previewPackageJsonTransform = (projectRoot, agent, installedAgents) => {
|
|
941
|
-
if (agent === "none") {
|
|
990
|
+
if (agent === "none" || agent === "ami") {
|
|
942
991
|
return {
|
|
943
992
|
success: true,
|
|
944
993
|
filePath: "",
|
|
945
|
-
message: "No agent selected, skipping package.json modification",
|
|
994
|
+
message: agent === "ami" ? "Ami does not require package.json modification" : "No agent selected, skipping package.json modification",
|
|
946
995
|
noChanges: true
|
|
947
996
|
};
|
|
948
997
|
}
|
|
@@ -1030,9 +1079,188 @@ var applyPackageJsonTransform = (result) => {
|
|
|
1030
1079
|
return { success: true };
|
|
1031
1080
|
};
|
|
1032
1081
|
|
|
1033
|
-
// src/
|
|
1034
|
-
var
|
|
1035
|
-
|
|
1082
|
+
// src/commands/add.ts
|
|
1083
|
+
var AGENT_NAMES = {
|
|
1084
|
+
"claude-code": "Claude Code",
|
|
1085
|
+
cursor: "Cursor",
|
|
1086
|
+
opencode: "Opencode",
|
|
1087
|
+
ami: "Ami"
|
|
1088
|
+
};
|
|
1089
|
+
var add = new commander.Command().name("add").description("add an agent integration").argument("[agent]", "agent to add (claude-code, cursor, opencode, ami)").option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1090
|
+
"-c, --cwd <cwd>",
|
|
1091
|
+
"working directory (defaults to current directory)",
|
|
1092
|
+
process.cwd()
|
|
1093
|
+
).action(async (agentArg, opts) => {
|
|
1094
|
+
try {
|
|
1095
|
+
const cwd = opts.cwd;
|
|
1096
|
+
const isNonInteractive = opts.yes;
|
|
1097
|
+
logger.log(`\u269B ${highlighter.info("React Grab")}`);
|
|
1098
|
+
logger.break();
|
|
1099
|
+
const preflightSpinner = spinner("Preflight checks.").start();
|
|
1100
|
+
const projectInfo = await detectProject(cwd);
|
|
1101
|
+
if (!projectInfo.hasReactGrab) {
|
|
1102
|
+
preflightSpinner.fail("React Grab is not installed.");
|
|
1103
|
+
logger.break();
|
|
1104
|
+
logger.error(
|
|
1105
|
+
`Run ${highlighter.info("react-grab init")} first to install React Grab.`
|
|
1106
|
+
);
|
|
1107
|
+
logger.break();
|
|
1108
|
+
process.exit(1);
|
|
1109
|
+
}
|
|
1110
|
+
preflightSpinner.succeed();
|
|
1111
|
+
const availableAgents = ["claude-code", "cursor", "opencode", "ami"].filter((agent) => !projectInfo.installedAgents.includes(agent));
|
|
1112
|
+
if (availableAgents.length === 0) {
|
|
1113
|
+
logger.break();
|
|
1114
|
+
logger.success("All agent integrations are already installed.");
|
|
1115
|
+
logger.break();
|
|
1116
|
+
process.exit(0);
|
|
1117
|
+
}
|
|
1118
|
+
let agentIntegration;
|
|
1119
|
+
if (agentArg) {
|
|
1120
|
+
if (!["claude-code", "cursor", "opencode", "ami"].includes(agentArg)) {
|
|
1121
|
+
logger.break();
|
|
1122
|
+
logger.error(`Invalid agent: ${agentArg}`);
|
|
1123
|
+
logger.error("Available agents: claude-code, cursor, opencode, ami");
|
|
1124
|
+
logger.break();
|
|
1125
|
+
process.exit(1);
|
|
1126
|
+
}
|
|
1127
|
+
if (projectInfo.installedAgents.includes(agentArg)) {
|
|
1128
|
+
logger.break();
|
|
1129
|
+
logger.warn(`${AGENT_NAMES[agentArg]} is already installed.`);
|
|
1130
|
+
logger.break();
|
|
1131
|
+
process.exit(0);
|
|
1132
|
+
}
|
|
1133
|
+
agentIntegration = agentArg;
|
|
1134
|
+
} else if (!isNonInteractive) {
|
|
1135
|
+
logger.break();
|
|
1136
|
+
const { agent } = await prompts2__default.default({
|
|
1137
|
+
type: "select",
|
|
1138
|
+
name: "agent",
|
|
1139
|
+
message: `Which ${highlighter.info("agent integration")} would you like to add?`,
|
|
1140
|
+
choices: availableAgents.map((innerAgent) => ({
|
|
1141
|
+
title: AGENT_NAMES[innerAgent],
|
|
1142
|
+
value: innerAgent
|
|
1143
|
+
}))
|
|
1144
|
+
});
|
|
1145
|
+
if (!agent) {
|
|
1146
|
+
logger.break();
|
|
1147
|
+
process.exit(1);
|
|
1148
|
+
}
|
|
1149
|
+
agentIntegration = agent;
|
|
1150
|
+
} else {
|
|
1151
|
+
logger.break();
|
|
1152
|
+
logger.error("Please specify an agent to add.");
|
|
1153
|
+
logger.error("Available agents: " + availableAgents.join(", "));
|
|
1154
|
+
logger.break();
|
|
1155
|
+
process.exit(1);
|
|
1156
|
+
}
|
|
1157
|
+
const addingSpinner = spinner(
|
|
1158
|
+
`Adding ${AGENT_NAMES[agentIntegration]}.`
|
|
1159
|
+
).start();
|
|
1160
|
+
addingSpinner.succeed();
|
|
1161
|
+
const result = previewTransform(
|
|
1162
|
+
projectInfo.projectRoot,
|
|
1163
|
+
projectInfo.framework,
|
|
1164
|
+
projectInfo.nextRouterType,
|
|
1165
|
+
agentIntegration,
|
|
1166
|
+
true
|
|
1167
|
+
);
|
|
1168
|
+
const packageJsonResult = previewPackageJsonTransform(
|
|
1169
|
+
projectInfo.projectRoot,
|
|
1170
|
+
agentIntegration,
|
|
1171
|
+
projectInfo.installedAgents
|
|
1172
|
+
);
|
|
1173
|
+
if (!result.success) {
|
|
1174
|
+
logger.break();
|
|
1175
|
+
logger.error(result.message);
|
|
1176
|
+
logger.break();
|
|
1177
|
+
process.exit(1);
|
|
1178
|
+
}
|
|
1179
|
+
const hasLayoutChanges = !result.noChanges && result.originalContent && result.newContent;
|
|
1180
|
+
const hasPackageJsonChanges = packageJsonResult.success && !packageJsonResult.noChanges && packageJsonResult.originalContent && packageJsonResult.newContent;
|
|
1181
|
+
if (hasLayoutChanges || hasPackageJsonChanges) {
|
|
1182
|
+
logger.break();
|
|
1183
|
+
if (hasLayoutChanges) {
|
|
1184
|
+
printDiff(result.filePath, result.originalContent, result.newContent);
|
|
1185
|
+
}
|
|
1186
|
+
if (hasPackageJsonChanges) {
|
|
1187
|
+
if (hasLayoutChanges) {
|
|
1188
|
+
logger.break();
|
|
1189
|
+
}
|
|
1190
|
+
printDiff(
|
|
1191
|
+
packageJsonResult.filePath,
|
|
1192
|
+
packageJsonResult.originalContent,
|
|
1193
|
+
packageJsonResult.newContent
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
if (!isNonInteractive) {
|
|
1197
|
+
logger.break();
|
|
1198
|
+
const { proceed } = await prompts2__default.default({
|
|
1199
|
+
type: "confirm",
|
|
1200
|
+
name: "proceed",
|
|
1201
|
+
message: "Apply these changes?",
|
|
1202
|
+
initial: true
|
|
1203
|
+
});
|
|
1204
|
+
if (!proceed) {
|
|
1205
|
+
logger.break();
|
|
1206
|
+
logger.log("Changes cancelled.");
|
|
1207
|
+
logger.break();
|
|
1208
|
+
process.exit(0);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
const packages = getPackagesToInstall(agentIntegration, false);
|
|
1213
|
+
if (packages.length > 0) {
|
|
1214
|
+
const installSpinner = spinner(
|
|
1215
|
+
`Installing ${packages.join(", ")}.`
|
|
1216
|
+
).start();
|
|
1217
|
+
try {
|
|
1218
|
+
installPackages(packages, projectInfo.packageManager, projectInfo.projectRoot);
|
|
1219
|
+
installSpinner.succeed();
|
|
1220
|
+
} catch (error) {
|
|
1221
|
+
installSpinner.fail();
|
|
1222
|
+
handleError(error);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
if (hasLayoutChanges) {
|
|
1226
|
+
const writeSpinner = spinner(`Applying changes to ${result.filePath}.`).start();
|
|
1227
|
+
const writeResult = applyTransform(result);
|
|
1228
|
+
if (!writeResult.success) {
|
|
1229
|
+
writeSpinner.fail();
|
|
1230
|
+
logger.break();
|
|
1231
|
+
logger.error(writeResult.error || "Failed to write file.");
|
|
1232
|
+
logger.break();
|
|
1233
|
+
process.exit(1);
|
|
1234
|
+
}
|
|
1235
|
+
writeSpinner.succeed();
|
|
1236
|
+
}
|
|
1237
|
+
if (hasPackageJsonChanges) {
|
|
1238
|
+
const packageJsonSpinner = spinner(
|
|
1239
|
+
`Applying changes to ${packageJsonResult.filePath}.`
|
|
1240
|
+
).start();
|
|
1241
|
+
const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
|
|
1242
|
+
if (!packageJsonWriteResult.success) {
|
|
1243
|
+
packageJsonSpinner.fail();
|
|
1244
|
+
logger.break();
|
|
1245
|
+
logger.error(packageJsonWriteResult.error || "Failed to write file.");
|
|
1246
|
+
logger.break();
|
|
1247
|
+
process.exit(1);
|
|
1248
|
+
}
|
|
1249
|
+
packageJsonSpinner.succeed();
|
|
1250
|
+
}
|
|
1251
|
+
logger.break();
|
|
1252
|
+
logger.log(
|
|
1253
|
+
`${highlighter.success("Success!")} ${AGENT_NAMES[agentIntegration]} has been added.`
|
|
1254
|
+
);
|
|
1255
|
+
logger.log("Make sure to start the agent server before using it.");
|
|
1256
|
+
logger.break();
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
handleError(error);
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
var VERSION = "0.0.74";
|
|
1262
|
+
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1263
|
+
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1036
1264
|
var reportToCli = async (type, config, error) => {
|
|
1037
1265
|
try {
|
|
1038
1266
|
await fetch(REPORT_URL, {
|
|
@@ -1062,416 +1290,155 @@ var PACKAGE_MANAGER_NAMES = {
|
|
|
1062
1290
|
pnpm: "pnpm",
|
|
1063
1291
|
bun: "Bun"
|
|
1064
1292
|
};
|
|
1065
|
-
var AGENT_NAMES = {
|
|
1066
|
-
"claude-code": "Claude Code",
|
|
1067
|
-
cursor: "Cursor",
|
|
1068
|
-
opencode: "Opencode"
|
|
1069
|
-
};
|
|
1070
1293
|
var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
1071
1294
|
remix: "Remix",
|
|
1072
1295
|
astro: "Astro",
|
|
1073
1296
|
sveltekit: "SvelteKit",
|
|
1074
1297
|
gatsby: "Gatsby"
|
|
1075
1298
|
};
|
|
1076
|
-
var
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
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(")}")}`);
|
|
1104
|
-
} else if (framework === "next" && nextRouterType === "pages") {
|
|
1105
|
-
console.log(`${pc__default.default.bold("Next.js Pages Router:")}`);
|
|
1106
|
-
console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
|
|
1107
|
-
console.log(` 2. Add to ${pc__default.default.cyan("pages/_document.tsx")} inside <Head>:`);
|
|
1108
|
-
console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
|
|
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(")}")}`);
|
|
1120
|
-
} else if (framework === "vite") {
|
|
1121
|
-
console.log(`${pc__default.default.bold("Vite:")}`);
|
|
1122
|
-
console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
|
|
1123
|
-
console.log(` 2. Add to ${pc__default.default.cyan("index.html")} inside <head>:`);
|
|
1124
|
-
console.log(` ${pc__default.default.gray('<script type="module">')}`);
|
|
1125
|
-
console.log(
|
|
1126
|
-
` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`
|
|
1127
|
-
);
|
|
1128
|
-
console.log(` ${pc__default.default.gray("</script>")}`);
|
|
1129
|
-
} else if (framework === "webpack") {
|
|
1130
|
-
console.log(`${pc__default.default.bold("Webpack:")}`);
|
|
1131
|
-
console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
|
|
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
|
-
);
|
|
1138
|
-
console.log(` ${pc__default.default.gray(' import("react-grab");')}`);
|
|
1139
|
-
console.log(` ${pc__default.default.gray("}")}`);
|
|
1140
|
-
} else {
|
|
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;
|
|
1188
|
-
}
|
|
1189
|
-
showDocsLink();
|
|
1190
|
-
};
|
|
1191
|
-
var showAccuracyWarning = () => {
|
|
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
|
-
);
|
|
1199
|
-
};
|
|
1200
|
-
var parseArgs = async () => {
|
|
1201
|
-
const argv = await yargs__default.default(helpers.hideBin(process.argv)).scriptName("react-grab").usage(
|
|
1202
|
-
`${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab CLI")} ${pc__default.default.gray(`v${VERSION}`)}
|
|
1203
|
-
|
|
1204
|
-
${pc__default.default.cyan("Usage:")} $0 [options]
|
|
1205
|
-
|
|
1206
|
-
React Grab adds AI-powered context selection to your React application,
|
|
1207
|
-
allowing you to select components and copy their context for AI assistants.
|
|
1208
|
-
|
|
1209
|
-
The CLI auto-detects your project configuration (framework, package manager,
|
|
1210
|
-
router type) and installs React Grab with optional agent integrations.`
|
|
1211
|
-
).option("framework", {
|
|
1212
|
-
alias: "f",
|
|
1213
|
-
type: "string",
|
|
1214
|
-
choices: ["next", "vite", "webpack"],
|
|
1215
|
-
description: "Override detected framework"
|
|
1216
|
-
}).option("package-manager", {
|
|
1217
|
-
alias: "p",
|
|
1218
|
-
type: "string",
|
|
1219
|
-
choices: ["npm", "yarn", "pnpm", "bun"],
|
|
1220
|
-
description: "Override detected package manager"
|
|
1221
|
-
}).option("router", {
|
|
1222
|
-
alias: "r",
|
|
1223
|
-
type: "string",
|
|
1224
|
-
choices: ["app", "pages"],
|
|
1225
|
-
description: "Next.js router type (only for Next.js projects)"
|
|
1226
|
-
}).option("agent", {
|
|
1227
|
-
alias: "a",
|
|
1228
|
-
type: "string",
|
|
1229
|
-
choices: ["claude-code", "cursor", "opencode", "none"],
|
|
1230
|
-
description: "Agent integration to automatically forward selected elements to agent instead of copying to clipboard"
|
|
1231
|
-
}).option("yes", {
|
|
1232
|
-
alias: "y",
|
|
1233
|
-
type: "boolean",
|
|
1234
|
-
default: false,
|
|
1235
|
-
description: "Skip all prompts and use auto-detected/default values"
|
|
1236
|
-
}).option("skip-install", {
|
|
1237
|
-
type: "boolean",
|
|
1238
|
-
default: false,
|
|
1239
|
-
description: "Only modify config files, skip npm/yarn/pnpm install"
|
|
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(
|
|
1247
|
-
`${pc__default.default.bold("Agent Integrations:")}
|
|
1248
|
-
${pc__default.default.cyan("claude-code")} Connect React Grab to Claude Code
|
|
1249
|
-
${pc__default.default.cyan("cursor")} Connect React Grab to Cursor IDE
|
|
1250
|
-
${pc__default.default.cyan("opencode")} Connect React Grab to Opencode
|
|
1251
|
-
|
|
1252
|
-
${pc__default.default.bold("Supported Frameworks:")}
|
|
1253
|
-
${pc__default.default.cyan("next")} Next.js (App Router & Pages Router)
|
|
1254
|
-
${pc__default.default.cyan("vite")} Vite-based React projects
|
|
1255
|
-
${pc__default.default.cyan("webpack")} Webpack-based React projects
|
|
1256
|
-
|
|
1257
|
-
${pc__default.default.bold("Documentation:")} ${pc__default.default.underline(DOCS_URL)}`
|
|
1258
|
-
).wrap(Math.min(100, process.stdout.columns || 80)).parse();
|
|
1259
|
-
return {
|
|
1260
|
-
framework: argv.framework,
|
|
1261
|
-
packageManager: argv["package-manager"],
|
|
1262
|
-
router: argv.router,
|
|
1263
|
-
agent: argv.agent,
|
|
1264
|
-
yes: argv.yes,
|
|
1265
|
-
skipInstall: argv["skip-install"]
|
|
1266
|
-
};
|
|
1267
|
-
};
|
|
1268
|
-
var main = async () => {
|
|
1269
|
-
const args = await parseArgs();
|
|
1270
|
-
const isNonInteractive = args.yes;
|
|
1271
|
-
console.log(
|
|
1272
|
-
`
|
|
1273
|
-
${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)}`
|
|
1274
|
-
);
|
|
1275
|
-
const projectInfo = await detectProject(process.cwd());
|
|
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
|
-
);
|
|
1282
|
-
if (projectInfo.framework === "next") {
|
|
1283
|
-
console.log(
|
|
1284
|
-
`- Router Type: ${pc__default.default.cyan(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`
|
|
1285
|
-
);
|
|
1286
|
-
}
|
|
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
|
-
);
|
|
1293
|
-
if (projectInfo.installedAgents.length > 0) {
|
|
1294
|
-
console.log(
|
|
1295
|
-
`- Agents: ${pc__default.default.cyan(projectInfo.installedAgents.map((agent) => AGENT_NAMES[agent] || agent).join(", "))}`
|
|
1296
|
-
);
|
|
1297
|
-
}
|
|
1298
|
-
console.log("");
|
|
1299
|
-
if (projectInfo.unsupportedFramework) {
|
|
1300
|
-
const frameworkName = UNSUPPORTED_FRAMEWORK_NAMES[projectInfo.unsupportedFramework];
|
|
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
|
-
);
|
|
1308
|
-
showManualInstructions(projectInfo.framework, projectInfo.nextRouterType);
|
|
1309
|
-
process.exit(0);
|
|
1310
|
-
}
|
|
1311
|
-
if (projectInfo.framework === "unknown") {
|
|
1312
|
-
if (projectInfo.isMonorepo && !isNonInteractive) {
|
|
1313
|
-
const workspaceProjects = findWorkspaceProjects(projectInfo.projectRoot);
|
|
1314
|
-
const reactProjects = workspaceProjects.filter(
|
|
1315
|
-
(p) => p.hasReact || p.framework !== "unknown"
|
|
1299
|
+
var init = new commander.Command().name("init").description("initialize React Grab in your project").option("-y, --yes", "skip confirmation prompts", false).option("-f, --force", "force overwrite existing config", false).option(
|
|
1300
|
+
"-a, --agent <agent>",
|
|
1301
|
+
"agent integration (claude-code, cursor, opencode, ami)"
|
|
1302
|
+
).option("--skip-install", "skip package installation", false).option(
|
|
1303
|
+
"-c, --cwd <cwd>",
|
|
1304
|
+
"working directory (defaults to current directory)",
|
|
1305
|
+
process.cwd()
|
|
1306
|
+
).action(async (opts) => {
|
|
1307
|
+
try {
|
|
1308
|
+
const cwd = opts.cwd;
|
|
1309
|
+
const isNonInteractive = opts.yes;
|
|
1310
|
+
logger.log(`\u269B ${highlighter.info("React Grab")}`);
|
|
1311
|
+
logger.break();
|
|
1312
|
+
const preflightSpinner = spinner("Preflight checks.").start();
|
|
1313
|
+
const projectInfo = await detectProject(cwd);
|
|
1314
|
+
if (projectInfo.hasReactGrab && !opts.force) {
|
|
1315
|
+
preflightSpinner.succeed();
|
|
1316
|
+
logger.break();
|
|
1317
|
+
logger.warn("React Grab is already installed.");
|
|
1318
|
+
logger.log(
|
|
1319
|
+
`Use ${highlighter.info("--force")} to reconfigure, or ${highlighter.info("react-grab add")} to add an agent.`
|
|
1316
1320
|
);
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1321
|
+
logger.break();
|
|
1322
|
+
process.exit(0);
|
|
1323
|
+
}
|
|
1324
|
+
preflightSpinner.succeed();
|
|
1325
|
+
const frameworkSpinner = spinner("Verifying framework.").start();
|
|
1326
|
+
if (projectInfo.unsupportedFramework) {
|
|
1327
|
+
const frameworkName = UNSUPPORTED_FRAMEWORK_NAMES[projectInfo.unsupportedFramework];
|
|
1328
|
+
frameworkSpinner.fail(`Found ${highlighter.info(frameworkName)}.`);
|
|
1329
|
+
logger.break();
|
|
1330
|
+
logger.log(`${frameworkName} is not yet supported by automatic setup.`);
|
|
1331
|
+
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1332
|
+
logger.break();
|
|
1333
|
+
process.exit(1);
|
|
1334
|
+
}
|
|
1335
|
+
if (projectInfo.framework === "unknown") {
|
|
1336
|
+
if (projectInfo.isMonorepo && !isNonInteractive) {
|
|
1337
|
+
frameworkSpinner.info("Verifying framework. Found monorepo.");
|
|
1338
|
+
const workspaceProjects = findWorkspaceProjects(
|
|
1339
|
+
projectInfo.projectRoot
|
|
1333
1340
|
);
|
|
1334
|
-
|
|
1335
|
-
|
|
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])}`
|
|
1341
|
+
const reactProjects = workspaceProjects.filter(
|
|
1342
|
+
(project) => project.hasReact || project.framework !== "unknown"
|
|
1343
1343
|
);
|
|
1344
|
-
if (
|
|
1345
|
-
|
|
1346
|
-
|
|
1344
|
+
if (reactProjects.length > 0) {
|
|
1345
|
+
logger.break();
|
|
1346
|
+
const sortedProjects = [...reactProjects].sort(
|
|
1347
|
+
(projectA, projectB) => {
|
|
1348
|
+
if (projectA.framework === "unknown" && projectB.framework !== "unknown")
|
|
1349
|
+
return 1;
|
|
1350
|
+
if (projectA.framework !== "unknown" && projectB.framework === "unknown")
|
|
1351
|
+
return -1;
|
|
1352
|
+
return 0;
|
|
1353
|
+
}
|
|
1347
1354
|
);
|
|
1355
|
+
const { selectedProject } = await prompts2__default.default({
|
|
1356
|
+
type: "select",
|
|
1357
|
+
name: "selectedProject",
|
|
1358
|
+
message: "Select a project to install React Grab:",
|
|
1359
|
+
choices: sortedProjects.map((project) => {
|
|
1360
|
+
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
1361
|
+
return {
|
|
1362
|
+
title: `${project.name}${frameworkLabel}`,
|
|
1363
|
+
value: project.path
|
|
1364
|
+
};
|
|
1365
|
+
})
|
|
1366
|
+
});
|
|
1367
|
+
if (!selectedProject) {
|
|
1368
|
+
logger.break();
|
|
1369
|
+
process.exit(1);
|
|
1370
|
+
}
|
|
1371
|
+
process.chdir(selectedProject);
|
|
1372
|
+
const newProjectInfo = await detectProject(selectedProject);
|
|
1373
|
+
Object.assign(projectInfo, newProjectInfo);
|
|
1374
|
+
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
1375
|
+
newFrameworkSpinner.succeed(
|
|
1376
|
+
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
|
|
1377
|
+
);
|
|
1378
|
+
} else {
|
|
1379
|
+
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
1380
|
+
logger.break();
|
|
1381
|
+
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1382
|
+
logger.break();
|
|
1383
|
+
process.exit(1);
|
|
1348
1384
|
}
|
|
1349
|
-
console.log(
|
|
1350
|
-
`- React Grab: ${newProjectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`
|
|
1351
|
-
);
|
|
1352
|
-
console.log("");
|
|
1353
1385
|
} else {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1386
|
+
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
1387
|
+
logger.break();
|
|
1388
|
+
logger.log(
|
|
1389
|
+
"React Grab supports Next.js, Vite, and Webpack projects."
|
|
1357
1390
|
);
|
|
1358
|
-
|
|
1359
|
-
|
|
1391
|
+
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1392
|
+
logger.break();
|
|
1393
|
+
process.exit(1);
|
|
1360
1394
|
}
|
|
1361
1395
|
} else {
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
`
|
|
1396
|
+
frameworkSpinner.succeed(
|
|
1397
|
+
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}.`
|
|
1365
1398
|
);
|
|
1366
|
-
showManualInstructions("unknown");
|
|
1367
|
-
process.exit(0);
|
|
1368
1399
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
} else if (projectInfo.hasReactGrab && args.agent && args.agent !== "none") {
|
|
1381
|
-
action = "add-agent";
|
|
1382
|
-
} else if (projectInfo.hasReactGrab && isNonInteractive && !args.agent) {
|
|
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
|
-
`
|
|
1400
|
+
if (projectInfo.framework === "next") {
|
|
1401
|
+
const routerSpinner = spinner("Detecting router type.").start();
|
|
1402
|
+
routerSpinner.succeed(
|
|
1403
|
+
`Detecting router type. Found ${highlighter.info(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}.`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
const packageManagerSpinner = spinner(
|
|
1407
|
+
"Detecting package manager."
|
|
1408
|
+
).start();
|
|
1409
|
+
packageManagerSpinner.succeed(
|
|
1410
|
+
`Detecting package manager. Found ${highlighter.info(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}.`
|
|
1389
1411
|
);
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
if (!confirmSettings) {
|
|
1401
|
-
finalFramework = await prompts.select({
|
|
1402
|
-
message: "Select your framework:",
|
|
1403
|
-
choices: [
|
|
1404
|
-
{ name: "Next.js", value: "next" },
|
|
1405
|
-
{ name: "Vite", value: "vite" },
|
|
1406
|
-
{ name: "Webpack", value: "webpack" }
|
|
1407
|
-
],
|
|
1408
|
-
default: projectInfo.framework
|
|
1409
|
-
});
|
|
1410
|
-
finalPackageManager = await prompts.select({
|
|
1411
|
-
message: "Select your package manager:",
|
|
1412
|
+
let finalFramework = projectInfo.framework;
|
|
1413
|
+
let finalPackageManager = projectInfo.packageManager;
|
|
1414
|
+
let finalNextRouterType = projectInfo.nextRouterType;
|
|
1415
|
+
let agentIntegration = opts.agent || "none";
|
|
1416
|
+
if (!isNonInteractive && !opts.agent) {
|
|
1417
|
+
logger.break();
|
|
1418
|
+
const { agent } = await prompts2__default.default({
|
|
1419
|
+
type: "select",
|
|
1420
|
+
name: "agent",
|
|
1421
|
+
message: `Would you like to add an ${highlighter.info("agent integration")}?`,
|
|
1412
1422
|
choices: [
|
|
1413
|
-
{
|
|
1414
|
-
{
|
|
1415
|
-
{
|
|
1416
|
-
{
|
|
1417
|
-
|
|
1418
|
-
|
|
1423
|
+
{ title: "None", value: "none" },
|
|
1424
|
+
{ title: "Claude Code", value: "claude-code" },
|
|
1425
|
+
{ title: "Cursor", value: "cursor" },
|
|
1426
|
+
{ title: "Opencode", value: "opencode" },
|
|
1427
|
+
{ title: "Ami", value: "ami" }
|
|
1428
|
+
]
|
|
1419
1429
|
});
|
|
1420
|
-
if (
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
choices: [
|
|
1424
|
-
{ name: "App Router", value: "app" },
|
|
1425
|
-
{ name: "Pages Router", value: "pages" }
|
|
1426
|
-
],
|
|
1427
|
-
default: projectInfo.nextRouterType === "app" ? "app" : "pages"
|
|
1428
|
-
});
|
|
1430
|
+
if (agent === void 0) {
|
|
1431
|
+
logger.break();
|
|
1432
|
+
process.exit(1);
|
|
1429
1433
|
}
|
|
1434
|
+
agentIntegration = agent;
|
|
1430
1435
|
}
|
|
1431
|
-
}
|
|
1432
|
-
let agentIntegration = args.agent || "none";
|
|
1433
|
-
const shouldAskForAgent = (action === "install-all" || action === "add-agent") && !args.agent;
|
|
1434
|
-
if (shouldAskForAgent && !isNonInteractive) {
|
|
1435
|
-
const availableAgents = [
|
|
1436
|
-
{ name: "Claude Code", value: "claude-code" },
|
|
1437
|
-
{ name: "Cursor", value: "cursor" },
|
|
1438
|
-
{ name: "Opencode", value: "opencode" }
|
|
1439
|
-
].filter((agent) => !projectInfo.installedAgents.includes(agent.value));
|
|
1440
|
-
if (availableAgents.length === 0) {
|
|
1441
|
-
console.log(
|
|
1442
|
-
`
|
|
1443
|
-
${pc__default.default.green("All agent integrations are already installed.")}
|
|
1444
|
-
`
|
|
1445
|
-
);
|
|
1446
|
-
} else if (action === "add-agent") {
|
|
1447
|
-
agentIntegration = await prompts.select({
|
|
1448
|
-
message: "Select an agent integration to add:",
|
|
1449
|
-
choices: availableAgents
|
|
1450
|
-
});
|
|
1451
|
-
} else {
|
|
1452
|
-
const wantAgentIntegration = await prompts.confirm({
|
|
1453
|
-
message: "Do you want to add an agent integration (Claude Code, Cursor, or Opencode)?",
|
|
1454
|
-
default: false
|
|
1455
|
-
});
|
|
1456
|
-
if (wantAgentIntegration) {
|
|
1457
|
-
agentIntegration = await prompts.select({
|
|
1458
|
-
message: "Select an agent integration:",
|
|
1459
|
-
choices: availableAgents
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
const shouldTransform = action === "reconfigure" || action === "install-all" || action === "add-agent" && agentIntegration !== "none";
|
|
1465
|
-
if (shouldTransform) {
|
|
1466
|
-
console.log(`
|
|
1467
|
-
${pc__default.default.magenta("\u269B")} Previewing changes...
|
|
1468
|
-
`);
|
|
1469
1436
|
const result = previewTransform(
|
|
1470
1437
|
projectInfo.projectRoot,
|
|
1471
1438
|
finalFramework,
|
|
1472
1439
|
finalNextRouterType,
|
|
1473
1440
|
agentIntegration,
|
|
1474
|
-
|
|
1441
|
+
false
|
|
1475
1442
|
);
|
|
1476
1443
|
const packageJsonResult = previewPackageJsonTransform(
|
|
1477
1444
|
projectInfo.projectRoot,
|
|
@@ -1479,24 +1446,26 @@ ${pc__default.default.magenta("\u269B")} Previewing changes...
|
|
|
1479
1446
|
projectInfo.installedAgents
|
|
1480
1447
|
);
|
|
1481
1448
|
if (!result.success) {
|
|
1482
|
-
|
|
1483
|
-
|
|
1449
|
+
logger.break();
|
|
1450
|
+
logger.error(result.message);
|
|
1451
|
+
logger.error(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1452
|
+
logger.break();
|
|
1484
1453
|
process.exit(1);
|
|
1485
1454
|
}
|
|
1486
1455
|
const hasLayoutChanges = !result.noChanges && result.originalContent && result.newContent;
|
|
1487
1456
|
const hasPackageJsonChanges = packageJsonResult.success && !packageJsonResult.noChanges && packageJsonResult.originalContent && packageJsonResult.newContent;
|
|
1488
|
-
if (
|
|
1489
|
-
|
|
1490
|
-
if (packageJsonResult.message) {
|
|
1491
|
-
console.log(`${pc__default.default.cyan("Info:")} ${packageJsonResult.message}`);
|
|
1492
|
-
}
|
|
1493
|
-
} else {
|
|
1457
|
+
if (hasLayoutChanges || hasPackageJsonChanges) {
|
|
1458
|
+
logger.break();
|
|
1494
1459
|
if (hasLayoutChanges) {
|
|
1495
|
-
printDiff(
|
|
1460
|
+
printDiff(
|
|
1461
|
+
result.filePath,
|
|
1462
|
+
result.originalContent,
|
|
1463
|
+
result.newContent
|
|
1464
|
+
);
|
|
1496
1465
|
}
|
|
1497
1466
|
if (hasPackageJsonChanges) {
|
|
1498
1467
|
if (hasLayoutChanges) {
|
|
1499
|
-
|
|
1468
|
+
logger.break();
|
|
1500
1469
|
}
|
|
1501
1470
|
printDiff(
|
|
1502
1471
|
packageJsonResult.filePath,
|
|
@@ -1504,104 +1473,101 @@ ${pc__default.default.magenta("\u269B")} Previewing changes...
|
|
|
1504
1473
|
packageJsonResult.newContent
|
|
1505
1474
|
);
|
|
1506
1475
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1476
|
+
logger.break();
|
|
1477
|
+
logger.warn("Auto-detection may not be 100% accurate.");
|
|
1478
|
+
logger.warn("Please verify the changes before committing.");
|
|
1479
|
+
if (!isNonInteractive) {
|
|
1480
|
+
logger.break();
|
|
1481
|
+
const { proceed } = await prompts2__default.default({
|
|
1482
|
+
type: "confirm",
|
|
1483
|
+
name: "proceed",
|
|
1484
|
+
message: "Apply these changes?",
|
|
1485
|
+
initial: true
|
|
1486
|
+
});
|
|
1487
|
+
if (!proceed) {
|
|
1488
|
+
logger.break();
|
|
1489
|
+
logger.log("Changes cancelled.");
|
|
1490
|
+
logger.break();
|
|
1491
|
+
process.exit(0);
|
|
1520
1492
|
}
|
|
1521
1493
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1494
|
+
}
|
|
1495
|
+
const shouldInstallReactGrab = !projectInfo.hasReactGrab;
|
|
1496
|
+
const shouldInstallAgent = agentIntegration !== "none" && !projectInfo.installedAgents.includes(agentIntegration);
|
|
1497
|
+
if (!opts.skipInstall && (shouldInstallReactGrab || shouldInstallAgent)) {
|
|
1498
|
+
const packages = getPackagesToInstall(
|
|
1499
|
+
agentIntegration,
|
|
1500
|
+
shouldInstallReactGrab
|
|
1501
|
+
);
|
|
1502
|
+
if (packages.length > 0) {
|
|
1503
|
+
const installSpinner = spinner(
|
|
1504
|
+
`Installing ${packages.join(", ")}.`
|
|
1505
|
+
).start();
|
|
1506
|
+
try {
|
|
1507
|
+
installPackages(
|
|
1508
|
+
packages,
|
|
1509
|
+
finalPackageManager,
|
|
1510
|
+
projectInfo.projectRoot
|
|
1534
1511
|
);
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
projectInfo.projectRoot
|
|
1540
|
-
);
|
|
1541
|
-
console.log(`
|
|
1542
|
-
${pc__default.default.green("Packages installed successfully!")}
|
|
1543
|
-
`);
|
|
1544
|
-
} catch (error) {
|
|
1545
|
-
console.error(`
|
|
1546
|
-
${pc__default.default.red("Failed to install packages:")}`, error);
|
|
1547
|
-
showDocsLink();
|
|
1548
|
-
process.exit(1);
|
|
1549
|
-
}
|
|
1512
|
+
installSpinner.succeed();
|
|
1513
|
+
} catch (error) {
|
|
1514
|
+
installSpinner.fail();
|
|
1515
|
+
handleError(error);
|
|
1550
1516
|
}
|
|
1551
1517
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1518
|
+
}
|
|
1519
|
+
if (hasLayoutChanges) {
|
|
1520
|
+
const writeSpinner = spinner(
|
|
1521
|
+
`Applying changes to ${result.filePath}.`
|
|
1522
|
+
).start();
|
|
1523
|
+
const writeResult = applyTransform(result);
|
|
1524
|
+
if (!writeResult.success) {
|
|
1525
|
+
writeSpinner.fail();
|
|
1526
|
+
logger.break();
|
|
1527
|
+
logger.error(writeResult.error || "Failed to write file.");
|
|
1528
|
+
logger.break();
|
|
1529
|
+
process.exit(1);
|
|
1562
1530
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1531
|
+
writeSpinner.succeed();
|
|
1532
|
+
}
|
|
1533
|
+
if (hasPackageJsonChanges) {
|
|
1534
|
+
const packageJsonSpinner = spinner(
|
|
1535
|
+
`Applying changes to ${packageJsonResult.filePath}.`
|
|
1536
|
+
).start();
|
|
1537
|
+
const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
|
|
1538
|
+
if (!packageJsonWriteResult.success) {
|
|
1539
|
+
packageJsonSpinner.fail();
|
|
1540
|
+
logger.break();
|
|
1541
|
+
logger.error(packageJsonWriteResult.error || "Failed to write file.");
|
|
1542
|
+
logger.break();
|
|
1543
|
+
process.exit(1);
|
|
1574
1544
|
}
|
|
1545
|
+
packageJsonSpinner.succeed();
|
|
1575
1546
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
console.log(`
|
|
1580
|
-
Next steps:`);
|
|
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)}
|
|
1584
|
-
`);
|
|
1585
|
-
if (agentIntegration !== "none") {
|
|
1586
|
-
console.log(
|
|
1587
|
-
`${pc__default.default.magenta("\u269B")} Agent: ${pc__default.default.cyan(AGENT_NAMES[agentIntegration])}`
|
|
1547
|
+
logger.break();
|
|
1548
|
+
logger.log(
|
|
1549
|
+
`${highlighter.success("Success!")} React Grab has been installed.`
|
|
1588
1550
|
);
|
|
1589
|
-
|
|
1590
|
-
|
|
1551
|
+
logger.log("You may now start your development server.");
|
|
1552
|
+
logger.break();
|
|
1553
|
+
await reportToCli("completed", {
|
|
1554
|
+
framework: finalFramework,
|
|
1555
|
+
packageManager: finalPackageManager,
|
|
1556
|
+
router: finalNextRouterType,
|
|
1557
|
+
agent: agentIntegration !== "none" ? agentIntegration : void 0,
|
|
1558
|
+
isMonorepo: projectInfo.isMonorepo
|
|
1559
|
+
});
|
|
1560
|
+
} catch (error) {
|
|
1561
|
+
handleError(error);
|
|
1562
|
+
await reportToCli("error", void 0, error);
|
|
1591
1563
|
}
|
|
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
|
-
});
|
|
1599
|
-
};
|
|
1600
|
-
main().catch(async (error) => {
|
|
1601
|
-
console.error(`${pc__default.default.red("Error:")}`, error);
|
|
1602
|
-
console.log("\nFor manual installation instructions, visit:");
|
|
1603
|
-
console.log(` ${DOCS_URL}
|
|
1604
|
-
`);
|
|
1605
|
-
await reportToCli("error", void 0, error);
|
|
1606
|
-
process.exit(1);
|
|
1607
1564
|
});
|
|
1565
|
+
|
|
1566
|
+
// src/cli.ts
|
|
1567
|
+
var VERSION2 = "0.0.74";
|
|
1568
|
+
process.on("SIGINT", () => process.exit(0));
|
|
1569
|
+
process.on("SIGTERM", () => process.exit(0));
|
|
1570
|
+
var program = new commander.Command().name("react-grab").description("add React Grab to your project").version(VERSION2, "-v, --version", "display the version number");
|
|
1571
|
+
program.addCommand(init);
|
|
1572
|
+
program.addCommand(add);
|
|
1573
|
+
program.parse();
|