@react-grab/cli 0.1.38 → 0.1.39
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 +86 -34
- package/dist/cli.js +89 -37
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -393,6 +393,45 @@ const handleError = (error) => {
|
|
|
393
393
|
process.exit(1);
|
|
394
394
|
};
|
|
395
395
|
//#endregion
|
|
396
|
+
//#region src/utils/detect-agents.ts
|
|
397
|
+
const PATH_BINARIES = {
|
|
398
|
+
"claude-code": ["claude"],
|
|
399
|
+
codex: ["codex"],
|
|
400
|
+
cursor: ["cursor", "cursor-agent"],
|
|
401
|
+
droid: ["droid"],
|
|
402
|
+
"gemini-cli": ["gemini"],
|
|
403
|
+
"github-copilot": ["copilot"],
|
|
404
|
+
opencode: ["opencode"],
|
|
405
|
+
pi: ["pi", "omegon"]
|
|
406
|
+
};
|
|
407
|
+
const isCommandAvailable = (command) => {
|
|
408
|
+
const pathDirectories = (process.env.PATH ?? "").split(node_path.delimiter).filter(Boolean);
|
|
409
|
+
for (const directory of pathDirectories) {
|
|
410
|
+
const binaryPath = (0, node_path.join)(directory, command);
|
|
411
|
+
try {
|
|
412
|
+
if ((0, node_fs.statSync)(binaryPath).isFile()) {
|
|
413
|
+
(0, node_fs.accessSync)(binaryPath, node_fs.constants.X_OK);
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
} catch {}
|
|
417
|
+
}
|
|
418
|
+
return false;
|
|
419
|
+
};
|
|
420
|
+
const detectAvailableAgents = async () => {
|
|
421
|
+
const installedAgents = new Set(await (0, agent_install_skill.detectInstalledSkillAgents)());
|
|
422
|
+
return (0, agent_install_skill.getSkillAgentTypes)().filter((agent) => {
|
|
423
|
+
if (agent === "universal") return false;
|
|
424
|
+
if (installedAgents.has(agent)) return true;
|
|
425
|
+
return PATH_BINARIES[agent]?.some(isCommandAvailable) ?? false;
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/utils/unref-stdin.ts
|
|
430
|
+
const unrefStdin = () => {
|
|
431
|
+
if (process.stdin.isTTY) return;
|
|
432
|
+
process.stdin.unref?.();
|
|
433
|
+
};
|
|
434
|
+
//#endregion
|
|
396
435
|
//#region src/utils/prompts.ts
|
|
397
436
|
const onCancel = () => {
|
|
398
437
|
logger.break();
|
|
@@ -401,7 +440,7 @@ const onCancel = () => {
|
|
|
401
440
|
process.exit(0);
|
|
402
441
|
};
|
|
403
442
|
const prompts$1 = (questions) => {
|
|
404
|
-
return (0, prompts.default)(questions, { onCancel });
|
|
443
|
+
return (0, prompts.default)(questions, { onCancel }).finally(unrefStdin);
|
|
405
444
|
};
|
|
406
445
|
//#endregion
|
|
407
446
|
//#region src/utils/spinner.ts
|
|
@@ -413,24 +452,32 @@ const SKILL_SOURCE = (0, node_url.fileURLToPath)(new URL("../skills/react-grab",
|
|
|
413
452
|
const agentLabel = (agent) => (0, agent_install_skill.getSkillAgentConfig)(agent).displayName;
|
|
414
453
|
const installedSkillDir = (agent) => (0, node_path.join)((0, agent_install_skill.isUniversalSkillAgent)(agent) ? (0, agent_install_skill.getCanonicalSkillsDir)(true) : (0, agent_install_skill.getSkillAgentDir)(agent, { global: true }), SKILL_NAME);
|
|
415
454
|
const promptSkillInstall = async ({ yes = false } = {}) => {
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
455
|
+
const detectedAgents = await detectAvailableAgents();
|
|
456
|
+
if (detectedAgents.length === 0) {
|
|
418
457
|
logger.warn("No supported agents detected.");
|
|
419
458
|
return false;
|
|
420
459
|
}
|
|
460
|
+
let selectedAgents = detectedAgents;
|
|
421
461
|
if (!yes) {
|
|
422
|
-
const {
|
|
423
|
-
type: "
|
|
424
|
-
name: "
|
|
425
|
-
message:
|
|
426
|
-
|
|
462
|
+
const { agents } = await prompts$1({
|
|
463
|
+
type: "multiselect",
|
|
464
|
+
name: "agents",
|
|
465
|
+
message: "Install the React Grab skill for:",
|
|
466
|
+
choices: detectedAgents.map((agent) => ({
|
|
467
|
+
title: agentLabel(agent),
|
|
468
|
+
value: agent,
|
|
469
|
+
selected: true
|
|
470
|
+
})),
|
|
471
|
+
instructions: false,
|
|
472
|
+
min: 1
|
|
427
473
|
});
|
|
428
|
-
|
|
474
|
+
selectedAgents = agents ?? [];
|
|
475
|
+
if (selectedAgents.length === 0) return false;
|
|
429
476
|
}
|
|
430
477
|
const installSpinner = spinner("Installing React Grab skill.").start();
|
|
431
478
|
const { installed, failed } = await (0, agent_install_skill.add)({
|
|
432
479
|
source: SKILL_SOURCE,
|
|
433
|
-
agents,
|
|
480
|
+
agents: selectedAgents,
|
|
434
481
|
global: true,
|
|
435
482
|
mode: "copy"
|
|
436
483
|
});
|
|
@@ -443,7 +490,7 @@ const promptSkillInstall = async ({ yes = false } = {}) => {
|
|
|
443
490
|
return true;
|
|
444
491
|
};
|
|
445
492
|
const removeSkill = async () => {
|
|
446
|
-
const agentsWithSkill = (await (
|
|
493
|
+
const agentsWithSkill = (await detectAvailableAgents()).filter((agent) => (0, node_fs.existsSync)(installedSkillDir(agent)));
|
|
447
494
|
for (const skillDir of new Set(agentsWithSkill.map(installedSkillDir))) (0, node_fs.rmSync)(skillDir, {
|
|
448
495
|
recursive: true,
|
|
449
496
|
force: true
|
|
@@ -453,7 +500,7 @@ const removeSkill = async () => {
|
|
|
453
500
|
};
|
|
454
501
|
//#endregion
|
|
455
502
|
//#region src/commands/add.ts
|
|
456
|
-
const VERSION$5 = "0.1.
|
|
503
|
+
const VERSION$5 = "0.1.39";
|
|
457
504
|
const add = new commander.Command().name("add").alias("install").description("install the React Grab skill for your agent").option("-y, --yes", "skip confirmation prompts", false).option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
458
505
|
console.log(`${picocolors.default.magenta("✿")} ${picocolors.default.bold("React Grab")} ${picocolors.default.gray(VERSION$5)}`);
|
|
459
506
|
console.log();
|
|
@@ -856,6 +903,15 @@ const transformTanStack = (projectRoot, reactGrabAlreadyConfigured, force = fals
|
|
|
856
903
|
newContent
|
|
857
904
|
};
|
|
858
905
|
};
|
|
906
|
+
const hasFrameworkEntryPoint = (projectRoot, framework, nextRouterType) => {
|
|
907
|
+
switch (framework) {
|
|
908
|
+
case "next": return nextRouterType === "app" ? findLayoutFile(projectRoot) !== null : findDocumentFile(projectRoot) !== null;
|
|
909
|
+
case "vite":
|
|
910
|
+
case "webpack": return findEntryFile(projectRoot) !== null;
|
|
911
|
+
case "tanstack": return findTanStackRootFile(projectRoot) !== null;
|
|
912
|
+
default: return false;
|
|
913
|
+
}
|
|
914
|
+
};
|
|
859
915
|
const previewTransform = (projectRoot, framework, nextRouterType, reactGrabAlreadyConfigured = false, force = false) => {
|
|
860
916
|
switch (framework) {
|
|
861
917
|
case "next":
|
|
@@ -1055,7 +1111,7 @@ const formatActivationKeyDisplay = (activationKey) => {
|
|
|
1055
1111
|
};
|
|
1056
1112
|
//#endregion
|
|
1057
1113
|
//#region src/commands/configure.ts
|
|
1058
|
-
const VERSION$4 = "0.1.
|
|
1114
|
+
const VERSION$4 = "0.1.39";
|
|
1059
1115
|
const isMac = process.platform === "darwin";
|
|
1060
1116
|
const META_LABEL = isMac ? "Cmd" : "Win";
|
|
1061
1117
|
const ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -1674,7 +1730,7 @@ const installPackagesWithFeedback = async (packages, packageManager, projectRoot
|
|
|
1674
1730
|
};
|
|
1675
1731
|
//#endregion
|
|
1676
1732
|
//#region src/commands/init.ts
|
|
1677
|
-
const VERSION$3 = "0.1.
|
|
1733
|
+
const VERSION$3 = "0.1.39";
|
|
1678
1734
|
const REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1679
1735
|
const DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1680
1736
|
const reportToCli = (type, config, error) => {
|
|
@@ -1732,6 +1788,15 @@ const printSubprojects = (searchRoot, sortedProjects) => {
|
|
|
1732
1788
|
logger.log(` ${highlighter.dim("$")} npx grab@latest init -c ${(0, node_path.relative)(searchRoot, sortedProjects[0].path)}`);
|
|
1733
1789
|
logger.break();
|
|
1734
1790
|
};
|
|
1791
|
+
const SUPPORTED_FRAMEWORKS_LINE = "React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.";
|
|
1792
|
+
const failWithManualSetup = (failingSpinner, message, { listSupportedFrameworks = false } = {}) => {
|
|
1793
|
+
failingSpinner.fail(message);
|
|
1794
|
+
logger.break();
|
|
1795
|
+
if (listSupportedFrameworks) logger.log(SUPPORTED_FRAMEWORKS_LINE);
|
|
1796
|
+
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1797
|
+
logger.break();
|
|
1798
|
+
process.exit(1);
|
|
1799
|
+
};
|
|
1735
1800
|
const init = new commander.Command().name("init").alias("setup").description("initialize React Grab in your project").option("-y, --yes", "skip confirmation prompts", false).option("-f, --force", "force overwrite existing config", false).option("-k, --key <key>", "activation key (e.g., Meta+K, Ctrl+Shift+G, Space)").option("--skip-install", "skip package installation", false).option("--pkg <pkg>", "custom package URL for CLI (e.g., grab)").option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
1736
1801
|
console.log(`${picocolors.default.magenta("✿")} ${picocolors.default.bold("React Grab")} ${picocolors.default.gray(VERSION$3)}`);
|
|
1737
1802
|
console.log();
|
|
@@ -1905,7 +1970,7 @@ const init = new commander.Command().name("init").alias("setup").description("in
|
|
|
1905
1970
|
logger.break();
|
|
1906
1971
|
process.exit(1);
|
|
1907
1972
|
}
|
|
1908
|
-
if (projectInfo.framework === "unknown") {
|
|
1973
|
+
if (projectInfo.framework === "unknown" || projectInfo.isMonorepo && !hasFrameworkEntryPoint(projectInfo.projectRoot, projectInfo.framework, projectInfo.nextRouterType)) {
|
|
1909
1974
|
let searchRoot = cwd;
|
|
1910
1975
|
let reactProjects = findReactProjects(searchRoot);
|
|
1911
1976
|
if (reactProjects.length === 0 && cwd !== process.cwd()) {
|
|
@@ -1943,23 +2008,10 @@ const init = new commander.Command().name("init").alias("setup").description("in
|
|
|
1943
2008
|
const newProjectInfo = await detectProject(selectedProject);
|
|
1944
2009
|
Object.assign(projectInfo, newProjectInfo);
|
|
1945
2010
|
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
1946
|
-
if (newProjectInfo.framework === "unknown") {
|
|
1947
|
-
newFrameworkSpinner.fail("Could not detect a supported framework in this project.");
|
|
1948
|
-
logger.break();
|
|
1949
|
-
logger.log("React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.");
|
|
1950
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1951
|
-
logger.break();
|
|
1952
|
-
process.exit(1);
|
|
1953
|
-
}
|
|
2011
|
+
if (newProjectInfo.framework === "unknown") failWithManualSetup(newFrameworkSpinner, "Could not detect a supported framework in this project.", { listSupportedFrameworks: true });
|
|
1954
2012
|
newFrameworkSpinner.succeed(`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`);
|
|
1955
|
-
} else {
|
|
1956
|
-
|
|
1957
|
-
logger.break();
|
|
1958
|
-
logger.log("React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.");
|
|
1959
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1960
|
-
logger.break();
|
|
1961
|
-
process.exit(1);
|
|
1962
|
-
}
|
|
2013
|
+
} else if (projectInfo.framework !== "unknown") failWithManualSetup(frameworkSpinner, `Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}, but could not find an entry file.`);
|
|
2014
|
+
else failWithManualSetup(frameworkSpinner, "Could not detect a supported framework.", { listSupportedFrameworks: true });
|
|
1963
2015
|
} else frameworkSpinner.succeed(`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}.`);
|
|
1964
2016
|
if (projectInfo.framework === "next") spinner("Detecting router type.").start().succeed(`Detecting router type. Found ${highlighter.info(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}.`);
|
|
1965
2017
|
spinner("Detecting package manager.").start().succeed(`Detecting package manager. Found ${highlighter.info(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}.`);
|
|
@@ -2023,7 +2075,7 @@ const init = new commander.Command().name("init").alias("setup").description("in
|
|
|
2023
2075
|
});
|
|
2024
2076
|
//#endregion
|
|
2025
2077
|
//#region src/commands/remove.ts
|
|
2026
|
-
const VERSION$2 = "0.1.
|
|
2078
|
+
const VERSION$2 = "0.1.39";
|
|
2027
2079
|
const remove = new commander.Command().name("remove").description("uninstall the React Grab skill from your agent").action(async () => {
|
|
2028
2080
|
console.log(`${picocolors.default.magenta("✿")} ${picocolors.default.bold("React Grab")} ${picocolors.default.gray(VERSION$2)}`);
|
|
2029
2081
|
console.log();
|
|
@@ -2040,7 +2092,7 @@ const remove = new commander.Command().name("remove").description("uninstall the
|
|
|
2040
2092
|
});
|
|
2041
2093
|
//#endregion
|
|
2042
2094
|
//#region src/commands/upgrade.ts
|
|
2043
|
-
const VERSION$1 = "0.1.
|
|
2095
|
+
const VERSION$1 = "0.1.39";
|
|
2044
2096
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org/react-grab/latest";
|
|
2045
2097
|
const fetchLatestVersion = async () => {
|
|
2046
2098
|
try {
|
|
@@ -2475,7 +2527,7 @@ const watch = new commander.Command().name("watch").description("watch the clipb
|
|
|
2475
2527
|
});
|
|
2476
2528
|
//#endregion
|
|
2477
2529
|
//#region src/cli.ts
|
|
2478
|
-
const VERSION = "0.1.
|
|
2530
|
+
const VERSION = "0.1.39";
|
|
2479
2531
|
const VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
2480
2532
|
process.on("SIGINT", () => process.exit(0));
|
|
2481
2533
|
process.on("SIGTERM", () => process.exit(0));
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import pc from "picocolors";
|
|
4
|
-
import fs, { accessSync, constants, existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
-
import path, { basename, dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import fs, { accessSync, constants, existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
|
+
import path, { basename, delimiter, dirname, join, relative, resolve } from "node:path";
|
|
6
6
|
import { detect } from "package-manager-detector/detect";
|
|
7
7
|
import ignore from "ignore";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { add, detectInstalledSkillAgents, getCanonicalSkillsDir, getSkillAgentConfig, getSkillAgentDir, isUniversalSkillAgent } from "agent-install/skill";
|
|
9
|
+
import { add, detectInstalledSkillAgents, getCanonicalSkillsDir, getSkillAgentConfig, getSkillAgentDir, getSkillAgentTypes, isUniversalSkillAgent } from "agent-install/skill";
|
|
10
10
|
import basePrompts from "prompts";
|
|
11
11
|
import ora from "ora";
|
|
12
12
|
import { x } from "tinyexec";
|
|
@@ -365,6 +365,45 @@ const handleError = (error) => {
|
|
|
365
365
|
process.exit(1);
|
|
366
366
|
};
|
|
367
367
|
//#endregion
|
|
368
|
+
//#region src/utils/detect-agents.ts
|
|
369
|
+
const PATH_BINARIES = {
|
|
370
|
+
"claude-code": ["claude"],
|
|
371
|
+
codex: ["codex"],
|
|
372
|
+
cursor: ["cursor", "cursor-agent"],
|
|
373
|
+
droid: ["droid"],
|
|
374
|
+
"gemini-cli": ["gemini"],
|
|
375
|
+
"github-copilot": ["copilot"],
|
|
376
|
+
opencode: ["opencode"],
|
|
377
|
+
pi: ["pi", "omegon"]
|
|
378
|
+
};
|
|
379
|
+
const isCommandAvailable = (command) => {
|
|
380
|
+
const pathDirectories = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
381
|
+
for (const directory of pathDirectories) {
|
|
382
|
+
const binaryPath = join(directory, command);
|
|
383
|
+
try {
|
|
384
|
+
if (statSync(binaryPath).isFile()) {
|
|
385
|
+
accessSync(binaryPath, constants.X_OK);
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
} catch {}
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
};
|
|
392
|
+
const detectAvailableAgents = async () => {
|
|
393
|
+
const installedAgents = new Set(await detectInstalledSkillAgents());
|
|
394
|
+
return getSkillAgentTypes().filter((agent) => {
|
|
395
|
+
if (agent === "universal") return false;
|
|
396
|
+
if (installedAgents.has(agent)) return true;
|
|
397
|
+
return PATH_BINARIES[agent]?.some(isCommandAvailable) ?? false;
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
//#endregion
|
|
401
|
+
//#region src/utils/unref-stdin.ts
|
|
402
|
+
const unrefStdin = () => {
|
|
403
|
+
if (process.stdin.isTTY) return;
|
|
404
|
+
process.stdin.unref?.();
|
|
405
|
+
};
|
|
406
|
+
//#endregion
|
|
368
407
|
//#region src/utils/prompts.ts
|
|
369
408
|
const onCancel = () => {
|
|
370
409
|
logger.break();
|
|
@@ -373,7 +412,7 @@ const onCancel = () => {
|
|
|
373
412
|
process.exit(0);
|
|
374
413
|
};
|
|
375
414
|
const prompts = (questions) => {
|
|
376
|
-
return basePrompts(questions, { onCancel });
|
|
415
|
+
return basePrompts(questions, { onCancel }).finally(unrefStdin);
|
|
377
416
|
};
|
|
378
417
|
//#endregion
|
|
379
418
|
//#region src/utils/spinner.ts
|
|
@@ -385,24 +424,32 @@ const SKILL_SOURCE = fileURLToPath(new URL("../skills/react-grab", import.meta.u
|
|
|
385
424
|
const agentLabel = (agent) => getSkillAgentConfig(agent).displayName;
|
|
386
425
|
const installedSkillDir = (agent) => join(isUniversalSkillAgent(agent) ? getCanonicalSkillsDir(true) : getSkillAgentDir(agent, { global: true }), SKILL_NAME);
|
|
387
426
|
const promptSkillInstall = async ({ yes = false } = {}) => {
|
|
388
|
-
const
|
|
389
|
-
if (
|
|
427
|
+
const detectedAgents = await detectAvailableAgents();
|
|
428
|
+
if (detectedAgents.length === 0) {
|
|
390
429
|
logger.warn("No supported agents detected.");
|
|
391
430
|
return false;
|
|
392
431
|
}
|
|
432
|
+
let selectedAgents = detectedAgents;
|
|
393
433
|
if (!yes) {
|
|
394
|
-
const {
|
|
395
|
-
type: "
|
|
396
|
-
name: "
|
|
397
|
-
message:
|
|
398
|
-
|
|
434
|
+
const { agents } = await prompts({
|
|
435
|
+
type: "multiselect",
|
|
436
|
+
name: "agents",
|
|
437
|
+
message: "Install the React Grab skill for:",
|
|
438
|
+
choices: detectedAgents.map((agent) => ({
|
|
439
|
+
title: agentLabel(agent),
|
|
440
|
+
value: agent,
|
|
441
|
+
selected: true
|
|
442
|
+
})),
|
|
443
|
+
instructions: false,
|
|
444
|
+
min: 1
|
|
399
445
|
});
|
|
400
|
-
|
|
446
|
+
selectedAgents = agents ?? [];
|
|
447
|
+
if (selectedAgents.length === 0) return false;
|
|
401
448
|
}
|
|
402
449
|
const installSpinner = spinner("Installing React Grab skill.").start();
|
|
403
450
|
const { installed, failed } = await add({
|
|
404
451
|
source: SKILL_SOURCE,
|
|
405
|
-
agents,
|
|
452
|
+
agents: selectedAgents,
|
|
406
453
|
global: true,
|
|
407
454
|
mode: "copy"
|
|
408
455
|
});
|
|
@@ -415,7 +462,7 @@ const promptSkillInstall = async ({ yes = false } = {}) => {
|
|
|
415
462
|
return true;
|
|
416
463
|
};
|
|
417
464
|
const removeSkill = async () => {
|
|
418
|
-
const agentsWithSkill = (await
|
|
465
|
+
const agentsWithSkill = (await detectAvailableAgents()).filter((agent) => existsSync(installedSkillDir(agent)));
|
|
419
466
|
for (const skillDir of new Set(agentsWithSkill.map(installedSkillDir))) rmSync(skillDir, {
|
|
420
467
|
recursive: true,
|
|
421
468
|
force: true
|
|
@@ -425,7 +472,7 @@ const removeSkill = async () => {
|
|
|
425
472
|
};
|
|
426
473
|
//#endregion
|
|
427
474
|
//#region src/commands/add.ts
|
|
428
|
-
const VERSION$5 = "0.1.
|
|
475
|
+
const VERSION$5 = "0.1.39";
|
|
429
476
|
const add$1 = new Command().name("add").alias("install").description("install the React Grab skill for your agent").option("-y, --yes", "skip confirmation prompts", false).option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
430
477
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$5)}`);
|
|
431
478
|
console.log();
|
|
@@ -828,6 +875,15 @@ const transformTanStack = (projectRoot, reactGrabAlreadyConfigured, force = fals
|
|
|
828
875
|
newContent
|
|
829
876
|
};
|
|
830
877
|
};
|
|
878
|
+
const hasFrameworkEntryPoint = (projectRoot, framework, nextRouterType) => {
|
|
879
|
+
switch (framework) {
|
|
880
|
+
case "next": return nextRouterType === "app" ? findLayoutFile(projectRoot) !== null : findDocumentFile(projectRoot) !== null;
|
|
881
|
+
case "vite":
|
|
882
|
+
case "webpack": return findEntryFile(projectRoot) !== null;
|
|
883
|
+
case "tanstack": return findTanStackRootFile(projectRoot) !== null;
|
|
884
|
+
default: return false;
|
|
885
|
+
}
|
|
886
|
+
};
|
|
831
887
|
const previewTransform = (projectRoot, framework, nextRouterType, reactGrabAlreadyConfigured = false, force = false) => {
|
|
832
888
|
switch (framework) {
|
|
833
889
|
case "next":
|
|
@@ -1027,7 +1083,7 @@ const formatActivationKeyDisplay = (activationKey) => {
|
|
|
1027
1083
|
};
|
|
1028
1084
|
//#endregion
|
|
1029
1085
|
//#region src/commands/configure.ts
|
|
1030
|
-
const VERSION$4 = "0.1.
|
|
1086
|
+
const VERSION$4 = "0.1.39";
|
|
1031
1087
|
const isMac = process.platform === "darwin";
|
|
1032
1088
|
const META_LABEL = isMac ? "Cmd" : "Win";
|
|
1033
1089
|
const ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -1646,7 +1702,7 @@ const installPackagesWithFeedback = async (packages, packageManager, projectRoot
|
|
|
1646
1702
|
};
|
|
1647
1703
|
//#endregion
|
|
1648
1704
|
//#region src/commands/init.ts
|
|
1649
|
-
const VERSION$3 = "0.1.
|
|
1705
|
+
const VERSION$3 = "0.1.39";
|
|
1650
1706
|
const REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1651
1707
|
const DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1652
1708
|
const reportToCli = (type, config, error) => {
|
|
@@ -1704,6 +1760,15 @@ const printSubprojects = (searchRoot, sortedProjects) => {
|
|
|
1704
1760
|
logger.log(` ${highlighter.dim("$")} npx grab@latest init -c ${relative(searchRoot, sortedProjects[0].path)}`);
|
|
1705
1761
|
logger.break();
|
|
1706
1762
|
};
|
|
1763
|
+
const SUPPORTED_FRAMEWORKS_LINE = "React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.";
|
|
1764
|
+
const failWithManualSetup = (failingSpinner, message, { listSupportedFrameworks = false } = {}) => {
|
|
1765
|
+
failingSpinner.fail(message);
|
|
1766
|
+
logger.break();
|
|
1767
|
+
if (listSupportedFrameworks) logger.log(SUPPORTED_FRAMEWORKS_LINE);
|
|
1768
|
+
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1769
|
+
logger.break();
|
|
1770
|
+
process.exit(1);
|
|
1771
|
+
};
|
|
1707
1772
|
const init = new Command().name("init").alias("setup").description("initialize React Grab in your project").option("-y, --yes", "skip confirmation prompts", false).option("-f, --force", "force overwrite existing config", false).option("-k, --key <key>", "activation key (e.g., Meta+K, Ctrl+Shift+G, Space)").option("--skip-install", "skip package installation", false).option("--pkg <pkg>", "custom package URL for CLI (e.g., grab)").option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
1708
1773
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$3)}`);
|
|
1709
1774
|
console.log();
|
|
@@ -1877,7 +1942,7 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1877
1942
|
logger.break();
|
|
1878
1943
|
process.exit(1);
|
|
1879
1944
|
}
|
|
1880
|
-
if (projectInfo.framework === "unknown") {
|
|
1945
|
+
if (projectInfo.framework === "unknown" || projectInfo.isMonorepo && !hasFrameworkEntryPoint(projectInfo.projectRoot, projectInfo.framework, projectInfo.nextRouterType)) {
|
|
1881
1946
|
let searchRoot = cwd;
|
|
1882
1947
|
let reactProjects = findReactProjects(searchRoot);
|
|
1883
1948
|
if (reactProjects.length === 0 && cwd !== process.cwd()) {
|
|
@@ -1915,23 +1980,10 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1915
1980
|
const newProjectInfo = await detectProject(selectedProject);
|
|
1916
1981
|
Object.assign(projectInfo, newProjectInfo);
|
|
1917
1982
|
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
1918
|
-
if (newProjectInfo.framework === "unknown") {
|
|
1919
|
-
newFrameworkSpinner.fail("Could not detect a supported framework in this project.");
|
|
1920
|
-
logger.break();
|
|
1921
|
-
logger.log("React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.");
|
|
1922
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1923
|
-
logger.break();
|
|
1924
|
-
process.exit(1);
|
|
1925
|
-
}
|
|
1983
|
+
if (newProjectInfo.framework === "unknown") failWithManualSetup(newFrameworkSpinner, "Could not detect a supported framework in this project.", { listSupportedFrameworks: true });
|
|
1926
1984
|
newFrameworkSpinner.succeed(`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`);
|
|
1927
|
-
} else {
|
|
1928
|
-
|
|
1929
|
-
logger.break();
|
|
1930
|
-
logger.log("React Grab supports Next.js, Vite, TanStack Start, and Webpack projects.");
|
|
1931
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
1932
|
-
logger.break();
|
|
1933
|
-
process.exit(1);
|
|
1934
|
-
}
|
|
1985
|
+
} else if (projectInfo.framework !== "unknown") failWithManualSetup(frameworkSpinner, `Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}, but could not find an entry file.`);
|
|
1986
|
+
else failWithManualSetup(frameworkSpinner, "Could not detect a supported framework.", { listSupportedFrameworks: true });
|
|
1935
1987
|
} else frameworkSpinner.succeed(`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}.`);
|
|
1936
1988
|
if (projectInfo.framework === "next") spinner("Detecting router type.").start().succeed(`Detecting router type. Found ${highlighter.info(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}.`);
|
|
1937
1989
|
spinner("Detecting package manager.").start().succeed(`Detecting package manager. Found ${highlighter.info(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}.`);
|
|
@@ -1995,7 +2047,7 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1995
2047
|
});
|
|
1996
2048
|
//#endregion
|
|
1997
2049
|
//#region src/commands/remove.ts
|
|
1998
|
-
const VERSION$2 = "0.1.
|
|
2050
|
+
const VERSION$2 = "0.1.39";
|
|
1999
2051
|
const remove = new Command().name("remove").description("uninstall the React Grab skill from your agent").action(async () => {
|
|
2000
2052
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$2)}`);
|
|
2001
2053
|
console.log();
|
|
@@ -2012,7 +2064,7 @@ const remove = new Command().name("remove").description("uninstall the React Gra
|
|
|
2012
2064
|
});
|
|
2013
2065
|
//#endregion
|
|
2014
2066
|
//#region src/commands/upgrade.ts
|
|
2015
|
-
const VERSION$1 = "0.1.
|
|
2067
|
+
const VERSION$1 = "0.1.39";
|
|
2016
2068
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org/react-grab/latest";
|
|
2017
2069
|
const fetchLatestVersion = async () => {
|
|
2018
2070
|
try {
|
|
@@ -2447,7 +2499,7 @@ const watch = new Command().name("watch").description("watch the clipboard for t
|
|
|
2447
2499
|
});
|
|
2448
2500
|
//#endregion
|
|
2449
2501
|
//#region src/cli.ts
|
|
2450
|
-
const VERSION = "0.1.
|
|
2502
|
+
const VERSION = "0.1.39";
|
|
2451
2503
|
const VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
2452
2504
|
process.on("SIGINT", () => process.exit(0));
|
|
2453
2505
|
process.on("SIGTERM", () => process.exit(0));
|