@react-grab/cli 0.0.85 → 0.0.86
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 +415 -18
- package/dist/cli.js +415 -18
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -255,7 +255,7 @@ var AGENT_PACKAGES = [
|
|
|
255
255
|
"@react-grab/gemini",
|
|
256
256
|
"@react-grab/amp",
|
|
257
257
|
"@react-grab/ami",
|
|
258
|
-
"@react-grab/
|
|
258
|
+
"@react-grab/visual-edit"
|
|
259
259
|
];
|
|
260
260
|
var detectUnsupportedFramework = (projectRoot) => {
|
|
261
261
|
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
@@ -1046,11 +1046,11 @@ var AGENT_PREFIXES = {
|
|
|
1046
1046
|
amp: "npx @react-grab/amp@latest &&"
|
|
1047
1047
|
};
|
|
1048
1048
|
var previewPackageJsonTransform = (projectRoot, agent, installedAgents) => {
|
|
1049
|
-
if (agent === "none" || agent === "ami" || agent === "
|
|
1049
|
+
if (agent === "none" || agent === "ami" || agent === "visual-edit") {
|
|
1050
1050
|
return {
|
|
1051
1051
|
success: true,
|
|
1052
1052
|
filePath: "",
|
|
1053
|
-
message: agent === "ami" || agent === "
|
|
1053
|
+
message: agent === "ami" || agent === "visual-edit" ? `${agent === "ami" ? "Ami" : "Visual Edit"} does not require package.json modification` : "No agent selected, skipping package.json modification",
|
|
1054
1054
|
noChanges: true
|
|
1055
1055
|
};
|
|
1056
1056
|
}
|
|
@@ -1137,9 +1137,197 @@ var applyPackageJsonTransform = (result) => {
|
|
|
1137
1137
|
}
|
|
1138
1138
|
return { success: true };
|
|
1139
1139
|
};
|
|
1140
|
+
var formatOptionsForNextjs = (options) => {
|
|
1141
|
+
const parts = [];
|
|
1142
|
+
if (options.activationKey) {
|
|
1143
|
+
const keyParts = [];
|
|
1144
|
+
if (options.activationKey.key)
|
|
1145
|
+
keyParts.push(`key: "${options.activationKey.key}"`);
|
|
1146
|
+
if (options.activationKey.metaKey) keyParts.push("metaKey: true");
|
|
1147
|
+
if (options.activationKey.ctrlKey) keyParts.push("ctrlKey: true");
|
|
1148
|
+
if (options.activationKey.shiftKey) keyParts.push("shiftKey: true");
|
|
1149
|
+
if (options.activationKey.altKey) keyParts.push("altKey: true");
|
|
1150
|
+
if (keyParts.length > 0) {
|
|
1151
|
+
parts.push(`activationKey: { ${keyParts.join(", ")} }`);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
if (options.activationMode) {
|
|
1155
|
+
parts.push(`activationMode: "${options.activationMode}"`);
|
|
1156
|
+
}
|
|
1157
|
+
if (options.keyHoldDuration !== void 0) {
|
|
1158
|
+
parts.push(`keyHoldDuration: ${options.keyHoldDuration}`);
|
|
1159
|
+
}
|
|
1160
|
+
if (options.allowActivationInsideInput !== void 0) {
|
|
1161
|
+
parts.push(
|
|
1162
|
+
`allowActivationInsideInput: ${options.allowActivationInsideInput}`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
if (options.maxContextLines !== void 0) {
|
|
1166
|
+
parts.push(`maxContextLines: ${options.maxContextLines}`);
|
|
1167
|
+
}
|
|
1168
|
+
return `{ ${parts.join(", ")} }`;
|
|
1169
|
+
};
|
|
1170
|
+
var formatOptionsAsJson = (options) => {
|
|
1171
|
+
const cleanOptions = {};
|
|
1172
|
+
if (options.activationKey) {
|
|
1173
|
+
const activationKey = {};
|
|
1174
|
+
if (options.activationKey.key) activationKey.key = options.activationKey.key;
|
|
1175
|
+
if (options.activationKey.metaKey) activationKey.metaKey = true;
|
|
1176
|
+
if (options.activationKey.ctrlKey) activationKey.ctrlKey = true;
|
|
1177
|
+
if (options.activationKey.shiftKey) activationKey.shiftKey = true;
|
|
1178
|
+
if (options.activationKey.altKey) activationKey.altKey = true;
|
|
1179
|
+
if (Object.keys(activationKey).length > 0) {
|
|
1180
|
+
cleanOptions.activationKey = activationKey;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
if (options.activationMode) {
|
|
1184
|
+
cleanOptions.activationMode = options.activationMode;
|
|
1185
|
+
}
|
|
1186
|
+
if (options.keyHoldDuration !== void 0) {
|
|
1187
|
+
cleanOptions.keyHoldDuration = options.keyHoldDuration;
|
|
1188
|
+
}
|
|
1189
|
+
if (options.allowActivationInsideInput !== void 0) {
|
|
1190
|
+
cleanOptions.allowActivationInsideInput = options.allowActivationInsideInput;
|
|
1191
|
+
}
|
|
1192
|
+
if (options.maxContextLines !== void 0) {
|
|
1193
|
+
cleanOptions.maxContextLines = options.maxContextLines;
|
|
1194
|
+
}
|
|
1195
|
+
return JSON.stringify(cleanOptions);
|
|
1196
|
+
};
|
|
1197
|
+
var findReactGrabFile = (projectRoot, framework, nextRouterType) => {
|
|
1198
|
+
switch (framework) {
|
|
1199
|
+
case "next":
|
|
1200
|
+
if (nextRouterType === "app") {
|
|
1201
|
+
return findLayoutFile(projectRoot);
|
|
1202
|
+
}
|
|
1203
|
+
return findDocumentFile(projectRoot);
|
|
1204
|
+
case "vite":
|
|
1205
|
+
return findIndexHtml(projectRoot);
|
|
1206
|
+
case "webpack":
|
|
1207
|
+
return findEntryFile(projectRoot);
|
|
1208
|
+
default:
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
var addOptionsToNextScript = (originalContent, options, filePath) => {
|
|
1213
|
+
const reactGrabScriptMatch = originalContent.match(
|
|
1214
|
+
/(<Script[^>]*react-grab[^>]*)(\/?>)/is
|
|
1215
|
+
);
|
|
1216
|
+
if (!reactGrabScriptMatch) {
|
|
1217
|
+
return {
|
|
1218
|
+
success: false,
|
|
1219
|
+
filePath,
|
|
1220
|
+
message: "Could not find React Grab Script tag"
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
const scriptTag = reactGrabScriptMatch[0];
|
|
1224
|
+
const scriptOpening = reactGrabScriptMatch[1];
|
|
1225
|
+
const scriptClosing = reactGrabScriptMatch[2];
|
|
1226
|
+
const existingDataOptionsMatch = scriptTag.match(
|
|
1227
|
+
/data-options=\{JSON\.stringify\([^)]+\)\}/
|
|
1228
|
+
);
|
|
1229
|
+
const dataOptionsAttr = `data-options={JSON.stringify(
|
|
1230
|
+
${formatOptionsForNextjs(options)}
|
|
1231
|
+
)}`;
|
|
1232
|
+
let newScriptTag;
|
|
1233
|
+
if (existingDataOptionsMatch) {
|
|
1234
|
+
newScriptTag = scriptTag.replace(existingDataOptionsMatch[0], dataOptionsAttr);
|
|
1235
|
+
} else {
|
|
1236
|
+
newScriptTag = `${scriptOpening}
|
|
1237
|
+
${dataOptionsAttr}
|
|
1238
|
+
${scriptClosing}`;
|
|
1239
|
+
}
|
|
1240
|
+
const newContent = originalContent.replace(scriptTag, newScriptTag);
|
|
1241
|
+
return {
|
|
1242
|
+
success: true,
|
|
1243
|
+
filePath,
|
|
1244
|
+
message: "Update React Grab options",
|
|
1245
|
+
originalContent,
|
|
1246
|
+
newContent
|
|
1247
|
+
};
|
|
1248
|
+
};
|
|
1249
|
+
var addOptionsToViteScript = (originalContent, options, filePath) => {
|
|
1250
|
+
const reactGrabImportMatch = originalContent.match(
|
|
1251
|
+
/import\s*\(\s*["']react-grab["']\s*\)/
|
|
1252
|
+
);
|
|
1253
|
+
if (!reactGrabImportMatch) {
|
|
1254
|
+
return {
|
|
1255
|
+
success: false,
|
|
1256
|
+
filePath,
|
|
1257
|
+
message: "Could not find React Grab import"
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
1261
|
+
const newImport = `import("react-grab").then((m) => m.init(${optionsJson}))`;
|
|
1262
|
+
const newContent = originalContent.replace(reactGrabImportMatch[0], newImport);
|
|
1263
|
+
return {
|
|
1264
|
+
success: true,
|
|
1265
|
+
filePath,
|
|
1266
|
+
message: "Update React Grab options",
|
|
1267
|
+
originalContent,
|
|
1268
|
+
newContent
|
|
1269
|
+
};
|
|
1270
|
+
};
|
|
1271
|
+
var addOptionsToWebpackImport = (originalContent, options, filePath) => {
|
|
1272
|
+
const reactGrabImportMatch = originalContent.match(
|
|
1273
|
+
/import\s*\(\s*["']react-grab["']\s*\)/
|
|
1274
|
+
);
|
|
1275
|
+
if (!reactGrabImportMatch) {
|
|
1276
|
+
return {
|
|
1277
|
+
success: false,
|
|
1278
|
+
filePath,
|
|
1279
|
+
message: "Could not find React Grab import"
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
1283
|
+
const newImport = `import("react-grab").then((m) => m.init(${optionsJson}))`;
|
|
1284
|
+
const newContent = originalContent.replace(reactGrabImportMatch[0], newImport);
|
|
1285
|
+
return {
|
|
1286
|
+
success: true,
|
|
1287
|
+
filePath,
|
|
1288
|
+
message: "Update React Grab options",
|
|
1289
|
+
originalContent,
|
|
1290
|
+
newContent
|
|
1291
|
+
};
|
|
1292
|
+
};
|
|
1293
|
+
var previewOptionsTransform = (projectRoot, framework, nextRouterType, options) => {
|
|
1294
|
+
const filePath = findReactGrabFile(projectRoot, framework, nextRouterType);
|
|
1295
|
+
if (!filePath) {
|
|
1296
|
+
return {
|
|
1297
|
+
success: false,
|
|
1298
|
+
filePath: "",
|
|
1299
|
+
message: "Could not find file containing React Grab configuration"
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
const originalContent = fs.readFileSync(filePath, "utf-8");
|
|
1303
|
+
if (!hasReactGrabCode(originalContent)) {
|
|
1304
|
+
return {
|
|
1305
|
+
success: false,
|
|
1306
|
+
filePath,
|
|
1307
|
+
message: "Could not find React Grab code in the file"
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
switch (framework) {
|
|
1311
|
+
case "next":
|
|
1312
|
+
return addOptionsToNextScript(originalContent, options, filePath);
|
|
1313
|
+
case "vite":
|
|
1314
|
+
return addOptionsToViteScript(originalContent, options, filePath);
|
|
1315
|
+
case "webpack":
|
|
1316
|
+
return addOptionsToWebpackImport(originalContent, options, filePath);
|
|
1317
|
+
default:
|
|
1318
|
+
return {
|
|
1319
|
+
success: false,
|
|
1320
|
+
filePath,
|
|
1321
|
+
message: `Unknown framework: ${framework}`
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
var applyOptionsTransform = (result) => {
|
|
1326
|
+
return applyTransform(result);
|
|
1327
|
+
};
|
|
1140
1328
|
|
|
1141
1329
|
// src/commands/add.ts
|
|
1142
|
-
var VERSION = "0.0.
|
|
1330
|
+
var VERSION = "0.0.86";
|
|
1143
1331
|
var AGENT_NAMES = {
|
|
1144
1332
|
"claude-code": "Claude Code",
|
|
1145
1333
|
cursor: "Cursor",
|
|
@@ -1148,18 +1336,18 @@ var AGENT_NAMES = {
|
|
|
1148
1336
|
gemini: "Gemini",
|
|
1149
1337
|
amp: "Amp",
|
|
1150
1338
|
ami: "Ami",
|
|
1151
|
-
|
|
1339
|
+
"visual-edit": "Visual Edit"
|
|
1152
1340
|
};
|
|
1153
1341
|
var add = new commander.Command().name("add").description("add an agent integration").argument(
|
|
1154
1342
|
"[agent]",
|
|
1155
|
-
"agent to add (claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1343
|
+
"agent to add (claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit)"
|
|
1156
1344
|
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1157
1345
|
"-c, --cwd <cwd>",
|
|
1158
1346
|
"working directory (defaults to current directory)",
|
|
1159
1347
|
process.cwd()
|
|
1160
1348
|
).action(async (agentArg, opts) => {
|
|
1161
1349
|
console.log(
|
|
1162
|
-
`${pc__default.default.magenta("\
|
|
1350
|
+
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)}`
|
|
1163
1351
|
);
|
|
1164
1352
|
console.log();
|
|
1165
1353
|
try {
|
|
@@ -1185,7 +1373,7 @@ var add = new commander.Command().name("add").description("add an agent integrat
|
|
|
1185
1373
|
"gemini",
|
|
1186
1374
|
"amp",
|
|
1187
1375
|
"ami",
|
|
1188
|
-
"
|
|
1376
|
+
"visual-edit"
|
|
1189
1377
|
].filter((agent) => !projectInfo.installedAgents.includes(agent));
|
|
1190
1378
|
if (availableAgents.length === 0) {
|
|
1191
1379
|
logger.break();
|
|
@@ -1208,7 +1396,7 @@ var add = new commander.Command().name("add").description("add an agent integrat
|
|
|
1208
1396
|
logger.break();
|
|
1209
1397
|
logger.error(`Invalid agent: ${agentArg}`);
|
|
1210
1398
|
logger.error(
|
|
1211
|
-
"Available agents: claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1399
|
+
"Available agents: claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit"
|
|
1212
1400
|
);
|
|
1213
1401
|
logger.break();
|
|
1214
1402
|
process.exit(1);
|
|
@@ -1357,7 +1545,215 @@ var add = new commander.Command().name("add").description("add an agent integrat
|
|
|
1357
1545
|
handleError(error);
|
|
1358
1546
|
}
|
|
1359
1547
|
});
|
|
1360
|
-
var VERSION2 = "0.0.
|
|
1548
|
+
var VERSION2 = "0.0.86";
|
|
1549
|
+
var MODIFIER_KEY_NAMES = {
|
|
1550
|
+
metaKey: process.platform === "darwin" ? "\u2318 Command" : "\u229E Windows",
|
|
1551
|
+
ctrlKey: "Ctrl",
|
|
1552
|
+
shiftKey: "Shift",
|
|
1553
|
+
altKey: process.platform === "darwin" ? "\u2325 Option" : "Alt"
|
|
1554
|
+
};
|
|
1555
|
+
var formatActivationKey = (activationKey) => {
|
|
1556
|
+
if (!activationKey) return "Default (Option/Alt)";
|
|
1557
|
+
const parts = [];
|
|
1558
|
+
if (activationKey.metaKey) parts.push(process.platform === "darwin" ? "\u2318" : "Win");
|
|
1559
|
+
if (activationKey.ctrlKey) parts.push("Ctrl");
|
|
1560
|
+
if (activationKey.shiftKey) parts.push("Shift");
|
|
1561
|
+
if (activationKey.altKey) parts.push(process.platform === "darwin" ? "\u2325" : "Alt");
|
|
1562
|
+
if (activationKey.key) parts.push(activationKey.key.toUpperCase());
|
|
1563
|
+
return parts.length > 0 ? parts.join(" + ") : "Default (Option/Alt)";
|
|
1564
|
+
};
|
|
1565
|
+
var configure = new commander.Command().name("configure").alias("config").description("configure React Grab options").option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1566
|
+
"-c, --cwd <cwd>",
|
|
1567
|
+
"working directory (defaults to current directory)",
|
|
1568
|
+
process.cwd()
|
|
1569
|
+
).action(async (opts) => {
|
|
1570
|
+
console.log(
|
|
1571
|
+
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION2)}`
|
|
1572
|
+
);
|
|
1573
|
+
console.log();
|
|
1574
|
+
try {
|
|
1575
|
+
const cwd = opts.cwd;
|
|
1576
|
+
const isNonInteractive = opts.yes;
|
|
1577
|
+
const preflightSpinner = spinner("Preflight checks.").start();
|
|
1578
|
+
const projectInfo = await detectProject(cwd);
|
|
1579
|
+
if (!projectInfo.hasReactGrab) {
|
|
1580
|
+
preflightSpinner.fail("React Grab is not installed.");
|
|
1581
|
+
logger.break();
|
|
1582
|
+
logger.error(
|
|
1583
|
+
`Run ${highlighter.info("react-grab init")} first to install React Grab.`
|
|
1584
|
+
);
|
|
1585
|
+
logger.break();
|
|
1586
|
+
process.exit(1);
|
|
1587
|
+
}
|
|
1588
|
+
preflightSpinner.succeed();
|
|
1589
|
+
if (isNonInteractive) {
|
|
1590
|
+
logger.break();
|
|
1591
|
+
logger.error("Configure command requires interactive mode.");
|
|
1592
|
+
logger.error("Remove the --yes flag to use interactive prompts.");
|
|
1593
|
+
logger.break();
|
|
1594
|
+
process.exit(1);
|
|
1595
|
+
}
|
|
1596
|
+
logger.break();
|
|
1597
|
+
logger.log(`Configure ${highlighter.info("React Grab")} options:`);
|
|
1598
|
+
logger.break();
|
|
1599
|
+
const collectedOptions = {};
|
|
1600
|
+
const { wantActivationKey } = await prompts2__default.default({
|
|
1601
|
+
type: "confirm",
|
|
1602
|
+
name: "wantActivationKey",
|
|
1603
|
+
message: `Configure ${highlighter.info("activation key")}?`,
|
|
1604
|
+
initial: false
|
|
1605
|
+
});
|
|
1606
|
+
if (wantActivationKey === void 0) {
|
|
1607
|
+
logger.break();
|
|
1608
|
+
process.exit(1);
|
|
1609
|
+
}
|
|
1610
|
+
if (wantActivationKey) {
|
|
1611
|
+
const { key } = await prompts2__default.default({
|
|
1612
|
+
type: "text",
|
|
1613
|
+
name: "key",
|
|
1614
|
+
message: "Enter the activation key (e.g., g, k, space):",
|
|
1615
|
+
initial: ""
|
|
1616
|
+
});
|
|
1617
|
+
if (key === void 0) {
|
|
1618
|
+
logger.break();
|
|
1619
|
+
process.exit(1);
|
|
1620
|
+
}
|
|
1621
|
+
const { modifiers } = await prompts2__default.default({
|
|
1622
|
+
type: "multiselect",
|
|
1623
|
+
name: "modifiers",
|
|
1624
|
+
message: "Select modifier keys (space to select, enter to confirm):",
|
|
1625
|
+
choices: [
|
|
1626
|
+
{ title: MODIFIER_KEY_NAMES.metaKey, value: "metaKey" },
|
|
1627
|
+
{ title: MODIFIER_KEY_NAMES.ctrlKey, value: "ctrlKey" },
|
|
1628
|
+
{ title: MODIFIER_KEY_NAMES.shiftKey, value: "shiftKey" },
|
|
1629
|
+
{ title: MODIFIER_KEY_NAMES.altKey, value: "altKey", selected: true }
|
|
1630
|
+
],
|
|
1631
|
+
hint: "- Space to select, Enter to confirm"
|
|
1632
|
+
});
|
|
1633
|
+
if (modifiers === void 0) {
|
|
1634
|
+
logger.break();
|
|
1635
|
+
process.exit(1);
|
|
1636
|
+
}
|
|
1637
|
+
collectedOptions.activationKey = {
|
|
1638
|
+
...key && { key: key.toLowerCase() },
|
|
1639
|
+
...modifiers.includes("metaKey") && { metaKey: true },
|
|
1640
|
+
...modifiers.includes("ctrlKey") && { ctrlKey: true },
|
|
1641
|
+
...modifiers.includes("shiftKey") && { shiftKey: true },
|
|
1642
|
+
...modifiers.includes("altKey") && { altKey: true }
|
|
1643
|
+
};
|
|
1644
|
+
logger.log(
|
|
1645
|
+
` Activation key: ${highlighter.info(formatActivationKey(collectedOptions.activationKey))}`
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
const { activationMode } = await prompts2__default.default({
|
|
1649
|
+
type: "select",
|
|
1650
|
+
name: "activationMode",
|
|
1651
|
+
message: `Select ${highlighter.info("activation mode")}:`,
|
|
1652
|
+
choices: [
|
|
1653
|
+
{ title: "Toggle (press to activate/deactivate)", value: "toggle" },
|
|
1654
|
+
{ title: "Hold (hold key to keep active)", value: "hold" }
|
|
1655
|
+
],
|
|
1656
|
+
initial: 0
|
|
1657
|
+
});
|
|
1658
|
+
if (activationMode === void 0) {
|
|
1659
|
+
logger.break();
|
|
1660
|
+
process.exit(1);
|
|
1661
|
+
}
|
|
1662
|
+
collectedOptions.activationMode = activationMode;
|
|
1663
|
+
if (activationMode === "hold") {
|
|
1664
|
+
const { keyHoldDuration } = await prompts2__default.default({
|
|
1665
|
+
type: "number",
|
|
1666
|
+
name: "keyHoldDuration",
|
|
1667
|
+
message: `Enter ${highlighter.info("key hold duration")} in milliseconds:`,
|
|
1668
|
+
initial: 150,
|
|
1669
|
+
min: 0,
|
|
1670
|
+
max: 2e3
|
|
1671
|
+
});
|
|
1672
|
+
if (keyHoldDuration === void 0) {
|
|
1673
|
+
logger.break();
|
|
1674
|
+
process.exit(1);
|
|
1675
|
+
}
|
|
1676
|
+
collectedOptions.keyHoldDuration = keyHoldDuration;
|
|
1677
|
+
}
|
|
1678
|
+
const { allowActivationInsideInput } = await prompts2__default.default({
|
|
1679
|
+
type: "confirm",
|
|
1680
|
+
name: "allowActivationInsideInput",
|
|
1681
|
+
message: `Allow activation ${highlighter.info("inside input fields")}?`,
|
|
1682
|
+
initial: true
|
|
1683
|
+
});
|
|
1684
|
+
if (allowActivationInsideInput === void 0) {
|
|
1685
|
+
logger.break();
|
|
1686
|
+
process.exit(1);
|
|
1687
|
+
}
|
|
1688
|
+
collectedOptions.allowActivationInsideInput = allowActivationInsideInput;
|
|
1689
|
+
const { maxContextLines } = await prompts2__default.default({
|
|
1690
|
+
type: "number",
|
|
1691
|
+
name: "maxContextLines",
|
|
1692
|
+
message: `Enter ${highlighter.info("max context lines")} to include:`,
|
|
1693
|
+
initial: 3,
|
|
1694
|
+
min: 0,
|
|
1695
|
+
max: 50
|
|
1696
|
+
});
|
|
1697
|
+
if (maxContextLines === void 0) {
|
|
1698
|
+
logger.break();
|
|
1699
|
+
process.exit(1);
|
|
1700
|
+
}
|
|
1701
|
+
collectedOptions.maxContextLines = maxContextLines;
|
|
1702
|
+
const result = previewOptionsTransform(
|
|
1703
|
+
projectInfo.projectRoot,
|
|
1704
|
+
projectInfo.framework,
|
|
1705
|
+
projectInfo.nextRouterType,
|
|
1706
|
+
collectedOptions
|
|
1707
|
+
);
|
|
1708
|
+
if (!result.success) {
|
|
1709
|
+
logger.break();
|
|
1710
|
+
logger.error(result.message);
|
|
1711
|
+
logger.break();
|
|
1712
|
+
process.exit(1);
|
|
1713
|
+
}
|
|
1714
|
+
const hasChanges = !result.noChanges && result.originalContent && result.newContent;
|
|
1715
|
+
if (hasChanges) {
|
|
1716
|
+
logger.break();
|
|
1717
|
+
printDiff(result.filePath, result.originalContent, result.newContent);
|
|
1718
|
+
logger.break();
|
|
1719
|
+
const { proceed } = await prompts2__default.default({
|
|
1720
|
+
type: "confirm",
|
|
1721
|
+
name: "proceed",
|
|
1722
|
+
message: "Apply these changes?",
|
|
1723
|
+
initial: true
|
|
1724
|
+
});
|
|
1725
|
+
if (!proceed) {
|
|
1726
|
+
logger.break();
|
|
1727
|
+
logger.log("Changes cancelled.");
|
|
1728
|
+
logger.break();
|
|
1729
|
+
process.exit(0);
|
|
1730
|
+
}
|
|
1731
|
+
const writeSpinner = spinner(
|
|
1732
|
+
`Applying changes to ${result.filePath}.`
|
|
1733
|
+
).start();
|
|
1734
|
+
const writeResult = applyOptionsTransform(result);
|
|
1735
|
+
if (!writeResult.success) {
|
|
1736
|
+
writeSpinner.fail();
|
|
1737
|
+
logger.break();
|
|
1738
|
+
logger.error(writeResult.error || "Failed to write file.");
|
|
1739
|
+
logger.break();
|
|
1740
|
+
process.exit(1);
|
|
1741
|
+
}
|
|
1742
|
+
writeSpinner.succeed();
|
|
1743
|
+
} else {
|
|
1744
|
+
logger.break();
|
|
1745
|
+
logger.log("No changes needed.");
|
|
1746
|
+
}
|
|
1747
|
+
logger.break();
|
|
1748
|
+
logger.log(
|
|
1749
|
+
`${highlighter.success("Success!")} React Grab options have been configured.`
|
|
1750
|
+
);
|
|
1751
|
+
logger.break();
|
|
1752
|
+
} catch (error) {
|
|
1753
|
+
handleError(error);
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
var VERSION3 = "0.0.86";
|
|
1361
1757
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1362
1758
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1363
1759
|
var reportToCli = async (type, config, error) => {
|
|
@@ -1367,7 +1763,7 @@ var reportToCli = async (type, config, error) => {
|
|
|
1367
1763
|
headers: { "Content-Type": "application/json" },
|
|
1368
1764
|
body: JSON.stringify({
|
|
1369
1765
|
type,
|
|
1370
|
-
version:
|
|
1766
|
+
version: VERSION3,
|
|
1371
1767
|
config,
|
|
1372
1768
|
error: error ? { message: error.message, stack: error.stack } : void 0,
|
|
1373
1769
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1397,14 +1793,14 @@ var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
|
1397
1793
|
};
|
|
1398
1794
|
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(
|
|
1399
1795
|
"-a, --agent <agent>",
|
|
1400
|
-
"agent integration (claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1796
|
+
"agent integration (claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit)"
|
|
1401
1797
|
).option("--skip-install", "skip package installation", false).option(
|
|
1402
1798
|
"-c, --cwd <cwd>",
|
|
1403
1799
|
"working directory (defaults to current directory)",
|
|
1404
1800
|
process.cwd()
|
|
1405
1801
|
).action(async (opts) => {
|
|
1406
1802
|
console.log(
|
|
1407
|
-
`${pc__default.default.magenta("\
|
|
1803
|
+
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION3)}`
|
|
1408
1804
|
);
|
|
1409
1805
|
console.log();
|
|
1410
1806
|
try {
|
|
@@ -1529,7 +1925,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
1529
1925
|
{ title: "Gemini", value: "gemini" },
|
|
1530
1926
|
{ title: "Amp", value: "amp" },
|
|
1531
1927
|
{ title: "Ami", value: "ami" },
|
|
1532
|
-
{ title: "
|
|
1928
|
+
{ title: "Visual Edit", value: "visual-edit" }
|
|
1533
1929
|
]
|
|
1534
1930
|
});
|
|
1535
1931
|
if (agent === void 0) {
|
|
@@ -1667,7 +2063,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
1667
2063
|
await reportToCli("error", void 0, error);
|
|
1668
2064
|
}
|
|
1669
2065
|
});
|
|
1670
|
-
var
|
|
2066
|
+
var VERSION4 = "0.0.86";
|
|
1671
2067
|
var DEFAULT_PROXY_PORT = 2e3;
|
|
1672
2068
|
var REACT_GRAB_SCRIPT = '<script src="//unpkg.com/react-grab/dist/index.global.js"></script>';
|
|
1673
2069
|
var buildProviderScript = (provider) => `<script src="//unpkg.com/${provider}/dist/client.global.js"></script>`;
|
|
@@ -1712,7 +2108,7 @@ var start = new commander.Command().name("start").alias("proxy").description("st
|
|
|
1712
2108
|
"provider package to run via npx (e.g., @react-grab/cursor)"
|
|
1713
2109
|
).action(async (urlArg, opts) => {
|
|
1714
2110
|
console.log(
|
|
1715
|
-
`${pc__default.default.magenta("\
|
|
2111
|
+
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION4)}`
|
|
1716
2112
|
);
|
|
1717
2113
|
console.log();
|
|
1718
2114
|
let url = urlArg;
|
|
@@ -1892,7 +2288,7 @@ var start = new commander.Command().name("start").alias("proxy").description("st
|
|
|
1892
2288
|
});
|
|
1893
2289
|
|
|
1894
2290
|
// src/cli.ts
|
|
1895
|
-
var
|
|
2291
|
+
var VERSION5 = "0.0.86";
|
|
1896
2292
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
1897
2293
|
process.on("SIGINT", () => process.exit(0));
|
|
1898
2294
|
process.on("SIGTERM", () => process.exit(0));
|
|
@@ -1901,8 +2297,9 @@ try {
|
|
|
1901
2297
|
});
|
|
1902
2298
|
} catch {
|
|
1903
2299
|
}
|
|
1904
|
-
var program = new commander.Command().name("react-grab").description("add React Grab to your project").version(
|
|
2300
|
+
var program = new commander.Command().name("react-grab").description("add React Grab to your project").version(VERSION5, "-v, --version", "display the version number");
|
|
1905
2301
|
program.addCommand(init);
|
|
1906
2302
|
program.addCommand(add);
|
|
2303
|
+
program.addCommand(configure);
|
|
1907
2304
|
program.addCommand(start);
|
|
1908
2305
|
program.parse();
|
package/dist/cli.js
CHANGED
|
@@ -247,7 +247,7 @@ var AGENT_PACKAGES = [
|
|
|
247
247
|
"@react-grab/gemini",
|
|
248
248
|
"@react-grab/amp",
|
|
249
249
|
"@react-grab/ami",
|
|
250
|
-
"@react-grab/
|
|
250
|
+
"@react-grab/visual-edit"
|
|
251
251
|
];
|
|
252
252
|
var detectUnsupportedFramework = (projectRoot) => {
|
|
253
253
|
const packageJsonPath = join(projectRoot, "package.json");
|
|
@@ -1038,11 +1038,11 @@ var AGENT_PREFIXES = {
|
|
|
1038
1038
|
amp: "npx @react-grab/amp@latest &&"
|
|
1039
1039
|
};
|
|
1040
1040
|
var previewPackageJsonTransform = (projectRoot, agent, installedAgents) => {
|
|
1041
|
-
if (agent === "none" || agent === "ami" || agent === "
|
|
1041
|
+
if (agent === "none" || agent === "ami" || agent === "visual-edit") {
|
|
1042
1042
|
return {
|
|
1043
1043
|
success: true,
|
|
1044
1044
|
filePath: "",
|
|
1045
|
-
message: agent === "ami" || agent === "
|
|
1045
|
+
message: agent === "ami" || agent === "visual-edit" ? `${agent === "ami" ? "Ami" : "Visual Edit"} does not require package.json modification` : "No agent selected, skipping package.json modification",
|
|
1046
1046
|
noChanges: true
|
|
1047
1047
|
};
|
|
1048
1048
|
}
|
|
@@ -1129,9 +1129,197 @@ var applyPackageJsonTransform = (result) => {
|
|
|
1129
1129
|
}
|
|
1130
1130
|
return { success: true };
|
|
1131
1131
|
};
|
|
1132
|
+
var formatOptionsForNextjs = (options) => {
|
|
1133
|
+
const parts = [];
|
|
1134
|
+
if (options.activationKey) {
|
|
1135
|
+
const keyParts = [];
|
|
1136
|
+
if (options.activationKey.key)
|
|
1137
|
+
keyParts.push(`key: "${options.activationKey.key}"`);
|
|
1138
|
+
if (options.activationKey.metaKey) keyParts.push("metaKey: true");
|
|
1139
|
+
if (options.activationKey.ctrlKey) keyParts.push("ctrlKey: true");
|
|
1140
|
+
if (options.activationKey.shiftKey) keyParts.push("shiftKey: true");
|
|
1141
|
+
if (options.activationKey.altKey) keyParts.push("altKey: true");
|
|
1142
|
+
if (keyParts.length > 0) {
|
|
1143
|
+
parts.push(`activationKey: { ${keyParts.join(", ")} }`);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
if (options.activationMode) {
|
|
1147
|
+
parts.push(`activationMode: "${options.activationMode}"`);
|
|
1148
|
+
}
|
|
1149
|
+
if (options.keyHoldDuration !== void 0) {
|
|
1150
|
+
parts.push(`keyHoldDuration: ${options.keyHoldDuration}`);
|
|
1151
|
+
}
|
|
1152
|
+
if (options.allowActivationInsideInput !== void 0) {
|
|
1153
|
+
parts.push(
|
|
1154
|
+
`allowActivationInsideInput: ${options.allowActivationInsideInput}`
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
if (options.maxContextLines !== void 0) {
|
|
1158
|
+
parts.push(`maxContextLines: ${options.maxContextLines}`);
|
|
1159
|
+
}
|
|
1160
|
+
return `{ ${parts.join(", ")} }`;
|
|
1161
|
+
};
|
|
1162
|
+
var formatOptionsAsJson = (options) => {
|
|
1163
|
+
const cleanOptions = {};
|
|
1164
|
+
if (options.activationKey) {
|
|
1165
|
+
const activationKey = {};
|
|
1166
|
+
if (options.activationKey.key) activationKey.key = options.activationKey.key;
|
|
1167
|
+
if (options.activationKey.metaKey) activationKey.metaKey = true;
|
|
1168
|
+
if (options.activationKey.ctrlKey) activationKey.ctrlKey = true;
|
|
1169
|
+
if (options.activationKey.shiftKey) activationKey.shiftKey = true;
|
|
1170
|
+
if (options.activationKey.altKey) activationKey.altKey = true;
|
|
1171
|
+
if (Object.keys(activationKey).length > 0) {
|
|
1172
|
+
cleanOptions.activationKey = activationKey;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (options.activationMode) {
|
|
1176
|
+
cleanOptions.activationMode = options.activationMode;
|
|
1177
|
+
}
|
|
1178
|
+
if (options.keyHoldDuration !== void 0) {
|
|
1179
|
+
cleanOptions.keyHoldDuration = options.keyHoldDuration;
|
|
1180
|
+
}
|
|
1181
|
+
if (options.allowActivationInsideInput !== void 0) {
|
|
1182
|
+
cleanOptions.allowActivationInsideInput = options.allowActivationInsideInput;
|
|
1183
|
+
}
|
|
1184
|
+
if (options.maxContextLines !== void 0) {
|
|
1185
|
+
cleanOptions.maxContextLines = options.maxContextLines;
|
|
1186
|
+
}
|
|
1187
|
+
return JSON.stringify(cleanOptions);
|
|
1188
|
+
};
|
|
1189
|
+
var findReactGrabFile = (projectRoot, framework, nextRouterType) => {
|
|
1190
|
+
switch (framework) {
|
|
1191
|
+
case "next":
|
|
1192
|
+
if (nextRouterType === "app") {
|
|
1193
|
+
return findLayoutFile(projectRoot);
|
|
1194
|
+
}
|
|
1195
|
+
return findDocumentFile(projectRoot);
|
|
1196
|
+
case "vite":
|
|
1197
|
+
return findIndexHtml(projectRoot);
|
|
1198
|
+
case "webpack":
|
|
1199
|
+
return findEntryFile(projectRoot);
|
|
1200
|
+
default:
|
|
1201
|
+
return null;
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
var addOptionsToNextScript = (originalContent, options, filePath) => {
|
|
1205
|
+
const reactGrabScriptMatch = originalContent.match(
|
|
1206
|
+
/(<Script[^>]*react-grab[^>]*)(\/?>)/is
|
|
1207
|
+
);
|
|
1208
|
+
if (!reactGrabScriptMatch) {
|
|
1209
|
+
return {
|
|
1210
|
+
success: false,
|
|
1211
|
+
filePath,
|
|
1212
|
+
message: "Could not find React Grab Script tag"
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
const scriptTag = reactGrabScriptMatch[0];
|
|
1216
|
+
const scriptOpening = reactGrabScriptMatch[1];
|
|
1217
|
+
const scriptClosing = reactGrabScriptMatch[2];
|
|
1218
|
+
const existingDataOptionsMatch = scriptTag.match(
|
|
1219
|
+
/data-options=\{JSON\.stringify\([^)]+\)\}/
|
|
1220
|
+
);
|
|
1221
|
+
const dataOptionsAttr = `data-options={JSON.stringify(
|
|
1222
|
+
${formatOptionsForNextjs(options)}
|
|
1223
|
+
)}`;
|
|
1224
|
+
let newScriptTag;
|
|
1225
|
+
if (existingDataOptionsMatch) {
|
|
1226
|
+
newScriptTag = scriptTag.replace(existingDataOptionsMatch[0], dataOptionsAttr);
|
|
1227
|
+
} else {
|
|
1228
|
+
newScriptTag = `${scriptOpening}
|
|
1229
|
+
${dataOptionsAttr}
|
|
1230
|
+
${scriptClosing}`;
|
|
1231
|
+
}
|
|
1232
|
+
const newContent = originalContent.replace(scriptTag, newScriptTag);
|
|
1233
|
+
return {
|
|
1234
|
+
success: true,
|
|
1235
|
+
filePath,
|
|
1236
|
+
message: "Update React Grab options",
|
|
1237
|
+
originalContent,
|
|
1238
|
+
newContent
|
|
1239
|
+
};
|
|
1240
|
+
};
|
|
1241
|
+
var addOptionsToViteScript = (originalContent, options, filePath) => {
|
|
1242
|
+
const reactGrabImportMatch = originalContent.match(
|
|
1243
|
+
/import\s*\(\s*["']react-grab["']\s*\)/
|
|
1244
|
+
);
|
|
1245
|
+
if (!reactGrabImportMatch) {
|
|
1246
|
+
return {
|
|
1247
|
+
success: false,
|
|
1248
|
+
filePath,
|
|
1249
|
+
message: "Could not find React Grab import"
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
1253
|
+
const newImport = `import("react-grab").then((m) => m.init(${optionsJson}))`;
|
|
1254
|
+
const newContent = originalContent.replace(reactGrabImportMatch[0], newImport);
|
|
1255
|
+
return {
|
|
1256
|
+
success: true,
|
|
1257
|
+
filePath,
|
|
1258
|
+
message: "Update React Grab options",
|
|
1259
|
+
originalContent,
|
|
1260
|
+
newContent
|
|
1261
|
+
};
|
|
1262
|
+
};
|
|
1263
|
+
var addOptionsToWebpackImport = (originalContent, options, filePath) => {
|
|
1264
|
+
const reactGrabImportMatch = originalContent.match(
|
|
1265
|
+
/import\s*\(\s*["']react-grab["']\s*\)/
|
|
1266
|
+
);
|
|
1267
|
+
if (!reactGrabImportMatch) {
|
|
1268
|
+
return {
|
|
1269
|
+
success: false,
|
|
1270
|
+
filePath,
|
|
1271
|
+
message: "Could not find React Grab import"
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
1275
|
+
const newImport = `import("react-grab").then((m) => m.init(${optionsJson}))`;
|
|
1276
|
+
const newContent = originalContent.replace(reactGrabImportMatch[0], newImport);
|
|
1277
|
+
return {
|
|
1278
|
+
success: true,
|
|
1279
|
+
filePath,
|
|
1280
|
+
message: "Update React Grab options",
|
|
1281
|
+
originalContent,
|
|
1282
|
+
newContent
|
|
1283
|
+
};
|
|
1284
|
+
};
|
|
1285
|
+
var previewOptionsTransform = (projectRoot, framework, nextRouterType, options) => {
|
|
1286
|
+
const filePath = findReactGrabFile(projectRoot, framework, nextRouterType);
|
|
1287
|
+
if (!filePath) {
|
|
1288
|
+
return {
|
|
1289
|
+
success: false,
|
|
1290
|
+
filePath: "",
|
|
1291
|
+
message: "Could not find file containing React Grab configuration"
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
const originalContent = readFileSync(filePath, "utf-8");
|
|
1295
|
+
if (!hasReactGrabCode(originalContent)) {
|
|
1296
|
+
return {
|
|
1297
|
+
success: false,
|
|
1298
|
+
filePath,
|
|
1299
|
+
message: "Could not find React Grab code in the file"
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
switch (framework) {
|
|
1303
|
+
case "next":
|
|
1304
|
+
return addOptionsToNextScript(originalContent, options, filePath);
|
|
1305
|
+
case "vite":
|
|
1306
|
+
return addOptionsToViteScript(originalContent, options, filePath);
|
|
1307
|
+
case "webpack":
|
|
1308
|
+
return addOptionsToWebpackImport(originalContent, options, filePath);
|
|
1309
|
+
default:
|
|
1310
|
+
return {
|
|
1311
|
+
success: false,
|
|
1312
|
+
filePath,
|
|
1313
|
+
message: `Unknown framework: ${framework}`
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
var applyOptionsTransform = (result) => {
|
|
1318
|
+
return applyTransform(result);
|
|
1319
|
+
};
|
|
1132
1320
|
|
|
1133
1321
|
// src/commands/add.ts
|
|
1134
|
-
var VERSION = "0.0.
|
|
1322
|
+
var VERSION = "0.0.86";
|
|
1135
1323
|
var AGENT_NAMES = {
|
|
1136
1324
|
"claude-code": "Claude Code",
|
|
1137
1325
|
cursor: "Cursor",
|
|
@@ -1140,18 +1328,18 @@ var AGENT_NAMES = {
|
|
|
1140
1328
|
gemini: "Gemini",
|
|
1141
1329
|
amp: "Amp",
|
|
1142
1330
|
ami: "Ami",
|
|
1143
|
-
|
|
1331
|
+
"visual-edit": "Visual Edit"
|
|
1144
1332
|
};
|
|
1145
1333
|
var add = new Command().name("add").description("add an agent integration").argument(
|
|
1146
1334
|
"[agent]",
|
|
1147
|
-
"agent to add (claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1335
|
+
"agent to add (claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit)"
|
|
1148
1336
|
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1149
1337
|
"-c, --cwd <cwd>",
|
|
1150
1338
|
"working directory (defaults to current directory)",
|
|
1151
1339
|
process.cwd()
|
|
1152
1340
|
).action(async (agentArg, opts) => {
|
|
1153
1341
|
console.log(
|
|
1154
|
-
`${pc.magenta("\
|
|
1342
|
+
`${pc.magenta("\u273F")} ${pc.bold("React Grab")} ${pc.gray(VERSION)}`
|
|
1155
1343
|
);
|
|
1156
1344
|
console.log();
|
|
1157
1345
|
try {
|
|
@@ -1177,7 +1365,7 @@ var add = new Command().name("add").description("add an agent integration").argu
|
|
|
1177
1365
|
"gemini",
|
|
1178
1366
|
"amp",
|
|
1179
1367
|
"ami",
|
|
1180
|
-
"
|
|
1368
|
+
"visual-edit"
|
|
1181
1369
|
].filter((agent) => !projectInfo.installedAgents.includes(agent));
|
|
1182
1370
|
if (availableAgents.length === 0) {
|
|
1183
1371
|
logger.break();
|
|
@@ -1200,7 +1388,7 @@ var add = new Command().name("add").description("add an agent integration").argu
|
|
|
1200
1388
|
logger.break();
|
|
1201
1389
|
logger.error(`Invalid agent: ${agentArg}`);
|
|
1202
1390
|
logger.error(
|
|
1203
|
-
"Available agents: claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1391
|
+
"Available agents: claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit"
|
|
1204
1392
|
);
|
|
1205
1393
|
logger.break();
|
|
1206
1394
|
process.exit(1);
|
|
@@ -1349,7 +1537,215 @@ var add = new Command().name("add").description("add an agent integration").argu
|
|
|
1349
1537
|
handleError(error);
|
|
1350
1538
|
}
|
|
1351
1539
|
});
|
|
1352
|
-
var VERSION2 = "0.0.
|
|
1540
|
+
var VERSION2 = "0.0.86";
|
|
1541
|
+
var MODIFIER_KEY_NAMES = {
|
|
1542
|
+
metaKey: process.platform === "darwin" ? "\u2318 Command" : "\u229E Windows",
|
|
1543
|
+
ctrlKey: "Ctrl",
|
|
1544
|
+
shiftKey: "Shift",
|
|
1545
|
+
altKey: process.platform === "darwin" ? "\u2325 Option" : "Alt"
|
|
1546
|
+
};
|
|
1547
|
+
var formatActivationKey = (activationKey) => {
|
|
1548
|
+
if (!activationKey) return "Default (Option/Alt)";
|
|
1549
|
+
const parts = [];
|
|
1550
|
+
if (activationKey.metaKey) parts.push(process.platform === "darwin" ? "\u2318" : "Win");
|
|
1551
|
+
if (activationKey.ctrlKey) parts.push("Ctrl");
|
|
1552
|
+
if (activationKey.shiftKey) parts.push("Shift");
|
|
1553
|
+
if (activationKey.altKey) parts.push(process.platform === "darwin" ? "\u2325" : "Alt");
|
|
1554
|
+
if (activationKey.key) parts.push(activationKey.key.toUpperCase());
|
|
1555
|
+
return parts.length > 0 ? parts.join(" + ") : "Default (Option/Alt)";
|
|
1556
|
+
};
|
|
1557
|
+
var configure = new Command().name("configure").alias("config").description("configure React Grab options").option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1558
|
+
"-c, --cwd <cwd>",
|
|
1559
|
+
"working directory (defaults to current directory)",
|
|
1560
|
+
process.cwd()
|
|
1561
|
+
).action(async (opts) => {
|
|
1562
|
+
console.log(
|
|
1563
|
+
`${pc.magenta("\u273F")} ${pc.bold("React Grab")} ${pc.gray(VERSION2)}`
|
|
1564
|
+
);
|
|
1565
|
+
console.log();
|
|
1566
|
+
try {
|
|
1567
|
+
const cwd = opts.cwd;
|
|
1568
|
+
const isNonInteractive = opts.yes;
|
|
1569
|
+
const preflightSpinner = spinner("Preflight checks.").start();
|
|
1570
|
+
const projectInfo = await detectProject(cwd);
|
|
1571
|
+
if (!projectInfo.hasReactGrab) {
|
|
1572
|
+
preflightSpinner.fail("React Grab is not installed.");
|
|
1573
|
+
logger.break();
|
|
1574
|
+
logger.error(
|
|
1575
|
+
`Run ${highlighter.info("react-grab init")} first to install React Grab.`
|
|
1576
|
+
);
|
|
1577
|
+
logger.break();
|
|
1578
|
+
process.exit(1);
|
|
1579
|
+
}
|
|
1580
|
+
preflightSpinner.succeed();
|
|
1581
|
+
if (isNonInteractive) {
|
|
1582
|
+
logger.break();
|
|
1583
|
+
logger.error("Configure command requires interactive mode.");
|
|
1584
|
+
logger.error("Remove the --yes flag to use interactive prompts.");
|
|
1585
|
+
logger.break();
|
|
1586
|
+
process.exit(1);
|
|
1587
|
+
}
|
|
1588
|
+
logger.break();
|
|
1589
|
+
logger.log(`Configure ${highlighter.info("React Grab")} options:`);
|
|
1590
|
+
logger.break();
|
|
1591
|
+
const collectedOptions = {};
|
|
1592
|
+
const { wantActivationKey } = await prompts2({
|
|
1593
|
+
type: "confirm",
|
|
1594
|
+
name: "wantActivationKey",
|
|
1595
|
+
message: `Configure ${highlighter.info("activation key")}?`,
|
|
1596
|
+
initial: false
|
|
1597
|
+
});
|
|
1598
|
+
if (wantActivationKey === void 0) {
|
|
1599
|
+
logger.break();
|
|
1600
|
+
process.exit(1);
|
|
1601
|
+
}
|
|
1602
|
+
if (wantActivationKey) {
|
|
1603
|
+
const { key } = await prompts2({
|
|
1604
|
+
type: "text",
|
|
1605
|
+
name: "key",
|
|
1606
|
+
message: "Enter the activation key (e.g., g, k, space):",
|
|
1607
|
+
initial: ""
|
|
1608
|
+
});
|
|
1609
|
+
if (key === void 0) {
|
|
1610
|
+
logger.break();
|
|
1611
|
+
process.exit(1);
|
|
1612
|
+
}
|
|
1613
|
+
const { modifiers } = await prompts2({
|
|
1614
|
+
type: "multiselect",
|
|
1615
|
+
name: "modifiers",
|
|
1616
|
+
message: "Select modifier keys (space to select, enter to confirm):",
|
|
1617
|
+
choices: [
|
|
1618
|
+
{ title: MODIFIER_KEY_NAMES.metaKey, value: "metaKey" },
|
|
1619
|
+
{ title: MODIFIER_KEY_NAMES.ctrlKey, value: "ctrlKey" },
|
|
1620
|
+
{ title: MODIFIER_KEY_NAMES.shiftKey, value: "shiftKey" },
|
|
1621
|
+
{ title: MODIFIER_KEY_NAMES.altKey, value: "altKey", selected: true }
|
|
1622
|
+
],
|
|
1623
|
+
hint: "- Space to select, Enter to confirm"
|
|
1624
|
+
});
|
|
1625
|
+
if (modifiers === void 0) {
|
|
1626
|
+
logger.break();
|
|
1627
|
+
process.exit(1);
|
|
1628
|
+
}
|
|
1629
|
+
collectedOptions.activationKey = {
|
|
1630
|
+
...key && { key: key.toLowerCase() },
|
|
1631
|
+
...modifiers.includes("metaKey") && { metaKey: true },
|
|
1632
|
+
...modifiers.includes("ctrlKey") && { ctrlKey: true },
|
|
1633
|
+
...modifiers.includes("shiftKey") && { shiftKey: true },
|
|
1634
|
+
...modifiers.includes("altKey") && { altKey: true }
|
|
1635
|
+
};
|
|
1636
|
+
logger.log(
|
|
1637
|
+
` Activation key: ${highlighter.info(formatActivationKey(collectedOptions.activationKey))}`
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
const { activationMode } = await prompts2({
|
|
1641
|
+
type: "select",
|
|
1642
|
+
name: "activationMode",
|
|
1643
|
+
message: `Select ${highlighter.info("activation mode")}:`,
|
|
1644
|
+
choices: [
|
|
1645
|
+
{ title: "Toggle (press to activate/deactivate)", value: "toggle" },
|
|
1646
|
+
{ title: "Hold (hold key to keep active)", value: "hold" }
|
|
1647
|
+
],
|
|
1648
|
+
initial: 0
|
|
1649
|
+
});
|
|
1650
|
+
if (activationMode === void 0) {
|
|
1651
|
+
logger.break();
|
|
1652
|
+
process.exit(1);
|
|
1653
|
+
}
|
|
1654
|
+
collectedOptions.activationMode = activationMode;
|
|
1655
|
+
if (activationMode === "hold") {
|
|
1656
|
+
const { keyHoldDuration } = await prompts2({
|
|
1657
|
+
type: "number",
|
|
1658
|
+
name: "keyHoldDuration",
|
|
1659
|
+
message: `Enter ${highlighter.info("key hold duration")} in milliseconds:`,
|
|
1660
|
+
initial: 150,
|
|
1661
|
+
min: 0,
|
|
1662
|
+
max: 2e3
|
|
1663
|
+
});
|
|
1664
|
+
if (keyHoldDuration === void 0) {
|
|
1665
|
+
logger.break();
|
|
1666
|
+
process.exit(1);
|
|
1667
|
+
}
|
|
1668
|
+
collectedOptions.keyHoldDuration = keyHoldDuration;
|
|
1669
|
+
}
|
|
1670
|
+
const { allowActivationInsideInput } = await prompts2({
|
|
1671
|
+
type: "confirm",
|
|
1672
|
+
name: "allowActivationInsideInput",
|
|
1673
|
+
message: `Allow activation ${highlighter.info("inside input fields")}?`,
|
|
1674
|
+
initial: true
|
|
1675
|
+
});
|
|
1676
|
+
if (allowActivationInsideInput === void 0) {
|
|
1677
|
+
logger.break();
|
|
1678
|
+
process.exit(1);
|
|
1679
|
+
}
|
|
1680
|
+
collectedOptions.allowActivationInsideInput = allowActivationInsideInput;
|
|
1681
|
+
const { maxContextLines } = await prompts2({
|
|
1682
|
+
type: "number",
|
|
1683
|
+
name: "maxContextLines",
|
|
1684
|
+
message: `Enter ${highlighter.info("max context lines")} to include:`,
|
|
1685
|
+
initial: 3,
|
|
1686
|
+
min: 0,
|
|
1687
|
+
max: 50
|
|
1688
|
+
});
|
|
1689
|
+
if (maxContextLines === void 0) {
|
|
1690
|
+
logger.break();
|
|
1691
|
+
process.exit(1);
|
|
1692
|
+
}
|
|
1693
|
+
collectedOptions.maxContextLines = maxContextLines;
|
|
1694
|
+
const result = previewOptionsTransform(
|
|
1695
|
+
projectInfo.projectRoot,
|
|
1696
|
+
projectInfo.framework,
|
|
1697
|
+
projectInfo.nextRouterType,
|
|
1698
|
+
collectedOptions
|
|
1699
|
+
);
|
|
1700
|
+
if (!result.success) {
|
|
1701
|
+
logger.break();
|
|
1702
|
+
logger.error(result.message);
|
|
1703
|
+
logger.break();
|
|
1704
|
+
process.exit(1);
|
|
1705
|
+
}
|
|
1706
|
+
const hasChanges = !result.noChanges && result.originalContent && result.newContent;
|
|
1707
|
+
if (hasChanges) {
|
|
1708
|
+
logger.break();
|
|
1709
|
+
printDiff(result.filePath, result.originalContent, result.newContent);
|
|
1710
|
+
logger.break();
|
|
1711
|
+
const { proceed } = await prompts2({
|
|
1712
|
+
type: "confirm",
|
|
1713
|
+
name: "proceed",
|
|
1714
|
+
message: "Apply these changes?",
|
|
1715
|
+
initial: true
|
|
1716
|
+
});
|
|
1717
|
+
if (!proceed) {
|
|
1718
|
+
logger.break();
|
|
1719
|
+
logger.log("Changes cancelled.");
|
|
1720
|
+
logger.break();
|
|
1721
|
+
process.exit(0);
|
|
1722
|
+
}
|
|
1723
|
+
const writeSpinner = spinner(
|
|
1724
|
+
`Applying changes to ${result.filePath}.`
|
|
1725
|
+
).start();
|
|
1726
|
+
const writeResult = applyOptionsTransform(result);
|
|
1727
|
+
if (!writeResult.success) {
|
|
1728
|
+
writeSpinner.fail();
|
|
1729
|
+
logger.break();
|
|
1730
|
+
logger.error(writeResult.error || "Failed to write file.");
|
|
1731
|
+
logger.break();
|
|
1732
|
+
process.exit(1);
|
|
1733
|
+
}
|
|
1734
|
+
writeSpinner.succeed();
|
|
1735
|
+
} else {
|
|
1736
|
+
logger.break();
|
|
1737
|
+
logger.log("No changes needed.");
|
|
1738
|
+
}
|
|
1739
|
+
logger.break();
|
|
1740
|
+
logger.log(
|
|
1741
|
+
`${highlighter.success("Success!")} React Grab options have been configured.`
|
|
1742
|
+
);
|
|
1743
|
+
logger.break();
|
|
1744
|
+
} catch (error) {
|
|
1745
|
+
handleError(error);
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
var VERSION3 = "0.0.86";
|
|
1353
1749
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1354
1750
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1355
1751
|
var reportToCli = async (type, config, error) => {
|
|
@@ -1359,7 +1755,7 @@ var reportToCli = async (type, config, error) => {
|
|
|
1359
1755
|
headers: { "Content-Type": "application/json" },
|
|
1360
1756
|
body: JSON.stringify({
|
|
1361
1757
|
type,
|
|
1362
|
-
version:
|
|
1758
|
+
version: VERSION3,
|
|
1363
1759
|
config,
|
|
1364
1760
|
error: error ? { message: error.message, stack: error.stack } : void 0,
|
|
1365
1761
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1389,14 +1785,14 @@ var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
|
1389
1785
|
};
|
|
1390
1786
|
var init = new 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(
|
|
1391
1787
|
"-a, --agent <agent>",
|
|
1392
|
-
"agent integration (claude-code, cursor, opencode, codex, gemini, amp, ami,
|
|
1788
|
+
"agent integration (claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit)"
|
|
1393
1789
|
).option("--skip-install", "skip package installation", false).option(
|
|
1394
1790
|
"-c, --cwd <cwd>",
|
|
1395
1791
|
"working directory (defaults to current directory)",
|
|
1396
1792
|
process.cwd()
|
|
1397
1793
|
).action(async (opts) => {
|
|
1398
1794
|
console.log(
|
|
1399
|
-
`${pc.magenta("\
|
|
1795
|
+
`${pc.magenta("\u273F")} ${pc.bold("React Grab")} ${pc.gray(VERSION3)}`
|
|
1400
1796
|
);
|
|
1401
1797
|
console.log();
|
|
1402
1798
|
try {
|
|
@@ -1521,7 +1917,7 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
1521
1917
|
{ title: "Gemini", value: "gemini" },
|
|
1522
1918
|
{ title: "Amp", value: "amp" },
|
|
1523
1919
|
{ title: "Ami", value: "ami" },
|
|
1524
|
-
{ title: "
|
|
1920
|
+
{ title: "Visual Edit", value: "visual-edit" }
|
|
1525
1921
|
]
|
|
1526
1922
|
});
|
|
1527
1923
|
if (agent === void 0) {
|
|
@@ -1659,7 +2055,7 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
1659
2055
|
await reportToCli("error", void 0, error);
|
|
1660
2056
|
}
|
|
1661
2057
|
});
|
|
1662
|
-
var
|
|
2058
|
+
var VERSION4 = "0.0.86";
|
|
1663
2059
|
var DEFAULT_PROXY_PORT = 2e3;
|
|
1664
2060
|
var REACT_GRAB_SCRIPT = '<script src="//unpkg.com/react-grab/dist/index.global.js"></script>';
|
|
1665
2061
|
var buildProviderScript = (provider) => `<script src="//unpkg.com/${provider}/dist/client.global.js"></script>`;
|
|
@@ -1704,7 +2100,7 @@ var start = new Command().name("start").alias("proxy").description("start a prox
|
|
|
1704
2100
|
"provider package to run via npx (e.g., @react-grab/cursor)"
|
|
1705
2101
|
).action(async (urlArg, opts) => {
|
|
1706
2102
|
console.log(
|
|
1707
|
-
`${pc.magenta("\
|
|
2103
|
+
`${pc.magenta("\u273F")} ${pc.bold("React Grab")} ${pc.gray(VERSION4)}`
|
|
1708
2104
|
);
|
|
1709
2105
|
console.log();
|
|
1710
2106
|
let url = urlArg;
|
|
@@ -1884,7 +2280,7 @@ var start = new Command().name("start").alias("proxy").description("start a prox
|
|
|
1884
2280
|
});
|
|
1885
2281
|
|
|
1886
2282
|
// src/cli.ts
|
|
1887
|
-
var
|
|
2283
|
+
var VERSION5 = "0.0.86";
|
|
1888
2284
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
1889
2285
|
process.on("SIGINT", () => process.exit(0));
|
|
1890
2286
|
process.on("SIGTERM", () => process.exit(0));
|
|
@@ -1893,8 +2289,9 @@ try {
|
|
|
1893
2289
|
});
|
|
1894
2290
|
} catch {
|
|
1895
2291
|
}
|
|
1896
|
-
var program = new Command().name("react-grab").description("add React Grab to your project").version(
|
|
2292
|
+
var program = new Command().name("react-grab").description("add React Grab to your project").version(VERSION5, "-v, --version", "display the version number");
|
|
1897
2293
|
program.addCommand(init);
|
|
1898
2294
|
program.addCommand(add);
|
|
2295
|
+
program.addCommand(configure);
|
|
1899
2296
|
program.addCommand(start);
|
|
1900
2297
|
program.parse();
|