@react-grab/cli 0.1.43 → 0.1.44-dev.099016d
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/README.md +3 -3
- package/dist/cli.cjs +188 -184
- package/dist/cli.js +188 -184
- package/dist/cli.js.map +1 -1
- package/package.json +1 -3
- package/skills/react-grab/SKILL.md +31 -10
package/dist/cli.js
CHANGED
|
@@ -25,6 +25,71 @@ const AGENT_ENVIRONMENT_VARIABLES = [
|
|
|
25
25
|
const isEnvironmentVariableSet = (variable) => Boolean(process.env[variable]);
|
|
26
26
|
const detectNonInteractive = (yesFlag) => yesFlag || AGENT_ENVIRONMENT_VARIABLES.some(isEnvironmentVariableSet) || !process.stdin.isTTY;
|
|
27
27
|
//#endregion
|
|
28
|
+
//#region src/utils/react-grab-code.ts
|
|
29
|
+
const REACT_GRAB_SPECIFIER_PATTERN = String.raw`react-grab(?:\/[^"']+)?`;
|
|
30
|
+
const stripComments = (content) => content.replace(/<!--[\s\S]*?-->/g, "").replace(/\{\/\*[\s\S]*?\*\/\}/g, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|\s)\/\/.*$/gm, "$1");
|
|
31
|
+
const stripTypeOnlyReactGrabImports = (content) => {
|
|
32
|
+
return content.replace(new RegExp(String.raw`import\s+type\s+[^;]+from\s+["']${REACT_GRAB_SPECIFIER_PATTERN}["'];?`, "g"), "").replace(new RegExp(String.raw`import\s*\{\s*type\s+[^,}]+(?:\s*,\s*type\s+[^,}]+)*\s*,?\s*\}\s*from\s+["']${REACT_GRAB_SPECIFIER_PATTERN}["'];?`, "g"), "");
|
|
33
|
+
};
|
|
34
|
+
const hasReactGrabSetupCode = (content) => {
|
|
35
|
+
const setupCandidateContent = stripTypeOnlyReactGrabImports(stripComments(content));
|
|
36
|
+
return [
|
|
37
|
+
new RegExp(String.raw`import\s*\(\s*["']${REACT_GRAB_SPECIFIER_PATTERN}["']\s*\)`),
|
|
38
|
+
new RegExp(String.raw`import\s+(?!type\b)(?:[^"';]+from\s+)?["']${REACT_GRAB_SPECIFIER_PATTERN}["']`),
|
|
39
|
+
new RegExp(String.raw`require\s*\(\s*["']${REACT_GRAB_SPECIFIER_PATTERN}["']\s*\)`),
|
|
40
|
+
/<Script[\s\S]*?src\s*=\s*(?:["'][^"']*react-grab[^"']*["']|\{(?:["'][^"']*react-grab[^"']*["']|`[^`]*react-grab[^`]*`)\})/i,
|
|
41
|
+
/<script[\s\S]*?src\s*=\s*["'][^"']*react-grab[^"']*["']/i
|
|
42
|
+
].some((pattern) => pattern.test(setupCandidateContent));
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/utils/react-grab-setup-files.ts
|
|
46
|
+
const COMPONENT_EXTENSIONS = [
|
|
47
|
+
"tsx",
|
|
48
|
+
"jsx",
|
|
49
|
+
"ts",
|
|
50
|
+
"js"
|
|
51
|
+
];
|
|
52
|
+
const INSTRUMENTATION_EXTENSIONS = [
|
|
53
|
+
"ts",
|
|
54
|
+
"tsx",
|
|
55
|
+
"js",
|
|
56
|
+
"jsx",
|
|
57
|
+
"mts",
|
|
58
|
+
"cts",
|
|
59
|
+
"mjs",
|
|
60
|
+
"cjs"
|
|
61
|
+
];
|
|
62
|
+
const ROUTE_EXTENSIONS = ["tsx", "jsx"];
|
|
63
|
+
const createFileCandidates = (projectRoot, directories, baseName, extensions) => {
|
|
64
|
+
const fileCandidates = [];
|
|
65
|
+
for (const directory of directories) for (const extension of extensions) fileCandidates.push(join(projectRoot, directory, `${baseName}.${extension}`));
|
|
66
|
+
return fileCandidates;
|
|
67
|
+
};
|
|
68
|
+
const findExistingFile = (fileCandidates) => {
|
|
69
|
+
for (const filePath of fileCandidates) if (existsSync(filePath)) return filePath;
|
|
70
|
+
return null;
|
|
71
|
+
};
|
|
72
|
+
const getLayoutFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["app", "src/app"], "layout", COMPONENT_EXTENSIONS);
|
|
73
|
+
const getDocumentFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["pages", "src/pages"], "_document", COMPONENT_EXTENSIONS);
|
|
74
|
+
const getInstrumentationFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["", "src"], "instrumentation-client", INSTRUMENTATION_EXTENSIONS);
|
|
75
|
+
const getIndexHtmlCandidates = (projectRoot) => [join(projectRoot, "index.html"), join(projectRoot, "public", "index.html")];
|
|
76
|
+
const getEntryFileCandidates = (projectRoot) => [...createFileCandidates(projectRoot, ["src"], "index", COMPONENT_EXTENSIONS), ...createFileCandidates(projectRoot, ["src"], "main", COMPONENT_EXTENSIONS)];
|
|
77
|
+
const getTanStackRootFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["src/routes", "app/routes"], "__root", ROUTE_EXTENSIONS);
|
|
78
|
+
const getReactGrabSetupFileCandidates = (projectRoot) => [
|
|
79
|
+
...getLayoutFileCandidates(projectRoot),
|
|
80
|
+
...getDocumentFileCandidates(projectRoot),
|
|
81
|
+
...getInstrumentationFileCandidates(projectRoot),
|
|
82
|
+
...getIndexHtmlCandidates(projectRoot),
|
|
83
|
+
...getEntryFileCandidates(projectRoot),
|
|
84
|
+
...getTanStackRootFileCandidates(projectRoot)
|
|
85
|
+
];
|
|
86
|
+
const findLayoutFile = (projectRoot) => findExistingFile(getLayoutFileCandidates(projectRoot));
|
|
87
|
+
const findDocumentFile = (projectRoot) => findExistingFile(getDocumentFileCandidates(projectRoot));
|
|
88
|
+
const findIndexHtml = (projectRoot) => findExistingFile(getIndexHtmlCandidates(projectRoot));
|
|
89
|
+
const findEntryFile = (projectRoot) => findExistingFile(getEntryFileCandidates(projectRoot));
|
|
90
|
+
const findTanStackRootFile = (projectRoot) => findExistingFile(getTanStackRootFileCandidates(projectRoot));
|
|
91
|
+
const isInstrumentationFile = (filePath) => /(?:^|[/\\])instrumentation-client\.[cm]?[jt]sx?$/.test(filePath);
|
|
92
|
+
//#endregion
|
|
28
93
|
//#region src/utils/detect.ts
|
|
29
94
|
const VALID_PACKAGE_MANAGERS = new Set([
|
|
30
95
|
"npm",
|
|
@@ -238,10 +303,14 @@ const scanDirectoryForProjects = (rootDirectory, ignorer, maxDepth, currentDepth
|
|
|
238
303
|
return projects;
|
|
239
304
|
};
|
|
240
305
|
const MAX_SCAN_DEPTH = 2;
|
|
306
|
+
const normalizePathForComparison = (filePath) => filePath.replace(/\\/g, "/");
|
|
241
307
|
const findReactProjects = (projectRoot) => {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
308
|
+
const monorepoRoot = detectMonorepo(projectRoot) ? projectRoot : findEnclosingMonorepoRoot(projectRoot);
|
|
309
|
+
if (monorepoRoot) {
|
|
310
|
+
const workspaceProjects = findWorkspaceProjects(monorepoRoot);
|
|
311
|
+
const localProject = projectRoot === monorepoRoot ? null : buildReactProject(projectRoot);
|
|
312
|
+
const projects = localProject ? [localProject, ...workspaceProjects.filter((project) => normalizePathForComparison(project.path) !== normalizePathForComparison(localProject.path))] : workspaceProjects;
|
|
313
|
+
if (projects.length > 0) return projects;
|
|
245
314
|
}
|
|
246
315
|
const scannedProjects = scanDirectoryForProjects(projectRoot, loadGitignore(projectRoot), MAX_SCAN_DEPTH);
|
|
247
316
|
if (scannedProjects.length > 0) return scannedProjects;
|
|
@@ -253,47 +322,20 @@ const findReactProjects = (projectRoot) => {
|
|
|
253
322
|
}
|
|
254
323
|
return [];
|
|
255
324
|
};
|
|
256
|
-
const
|
|
325
|
+
const hasReactGrabSetupInFile = (filePath) => {
|
|
257
326
|
if (!existsSync(filePath)) return false;
|
|
258
327
|
try {
|
|
259
|
-
|
|
260
|
-
return [
|
|
261
|
-
/["'`][^"'`]*react-grab/,
|
|
262
|
-
/react-grab[^"'`]*["'`]/,
|
|
263
|
-
/<[^>]*react-grab/i,
|
|
264
|
-
/import[^;]*react-grab/i,
|
|
265
|
-
/require[^)]*react-grab/i,
|
|
266
|
-
/from\s+[^;]*react-grab/i,
|
|
267
|
-
/src[^>]*react-grab/i
|
|
268
|
-
].some((pattern) => pattern.test(content));
|
|
328
|
+
return hasReactGrabSetupCode(readFileSync(filePath, "utf-8"));
|
|
269
329
|
} catch {
|
|
270
330
|
return false;
|
|
271
331
|
}
|
|
272
332
|
};
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
return [
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
join(projectRoot, "src", "app", "layout.jsx"),
|
|
280
|
-
join(projectRoot, "pages", "_document.tsx"),
|
|
281
|
-
join(projectRoot, "pages", "_document.jsx"),
|
|
282
|
-
join(projectRoot, "instrumentation-client.ts"),
|
|
283
|
-
join(projectRoot, "instrumentation-client.js"),
|
|
284
|
-
join(projectRoot, "src", "instrumentation-client.ts"),
|
|
285
|
-
join(projectRoot, "src", "instrumentation-client.js"),
|
|
286
|
-
join(projectRoot, "index.html"),
|
|
287
|
-
join(projectRoot, "public", "index.html"),
|
|
288
|
-
join(projectRoot, "src", "index.tsx"),
|
|
289
|
-
join(projectRoot, "src", "index.ts"),
|
|
290
|
-
join(projectRoot, "src", "main.tsx"),
|
|
291
|
-
join(projectRoot, "src", "main.ts"),
|
|
292
|
-
join(projectRoot, "src", "routes", "__root.tsx"),
|
|
293
|
-
join(projectRoot, "src", "routes", "__root.jsx"),
|
|
294
|
-
join(projectRoot, "app", "routes", "__root.tsx"),
|
|
295
|
-
join(projectRoot, "app", "routes", "__root.jsx")
|
|
296
|
-
].some(hasReactGrabInFile);
|
|
333
|
+
const detectReactGrabDependency = (projectRoot) => {
|
|
334
|
+
const dependencies = readMergedDependencies(projectRoot);
|
|
335
|
+
return Boolean(dependencies?.["react-grab"]);
|
|
336
|
+
};
|
|
337
|
+
const detectReactGrabConfigured = (projectRoot) => {
|
|
338
|
+
return getReactGrabSetupFileCandidates(projectRoot).some(hasReactGrabSetupInFile);
|
|
297
339
|
};
|
|
298
340
|
const detectUnsupportedFramework = (projectRoot) => {
|
|
299
341
|
const dependencies = readMergedDependencies(projectRoot);
|
|
@@ -314,13 +356,17 @@ const detectReactGrabVersion = (projectRoot) => {
|
|
|
314
356
|
const detectProject = async (projectRoot = process.cwd()) => {
|
|
315
357
|
const localFramework = detectFramework(projectRoot);
|
|
316
358
|
const framework = localFramework === "unknown" ? detectFrameworkFromMonorepoRoot(projectRoot) : localFramework;
|
|
359
|
+
const packageManager = await detectPackageManager(projectRoot);
|
|
360
|
+
const isMonorepo = detectMonorepo(projectRoot) || findEnclosingMonorepoRoot(projectRoot) !== null;
|
|
361
|
+
const isReactGrabConfigured = detectReactGrabConfigured(projectRoot);
|
|
317
362
|
return {
|
|
318
|
-
packageManager
|
|
363
|
+
packageManager,
|
|
319
364
|
framework,
|
|
320
365
|
nextRouterType: framework === "next" ? detectNextRouterType(projectRoot) : "unknown",
|
|
321
|
-
isMonorepo
|
|
366
|
+
isMonorepo,
|
|
322
367
|
projectRoot,
|
|
323
|
-
hasReactGrab:
|
|
368
|
+
hasReactGrab: detectReactGrabDependency(projectRoot) || isReactGrabConfigured,
|
|
369
|
+
isReactGrabConfigured,
|
|
324
370
|
reactGrabVersion: detectReactGrabVersion(projectRoot),
|
|
325
371
|
unsupportedFramework: detectUnsupportedFramework(projectRoot)
|
|
326
372
|
};
|
|
@@ -434,6 +480,13 @@ const promptSkillInstall = async ({ yes = false, global = false, cwd = process.c
|
|
|
434
480
|
}
|
|
435
481
|
let selectedAgents = detectedAgents;
|
|
436
482
|
if (!yes) {
|
|
483
|
+
const { confirmed } = await prompts({
|
|
484
|
+
type: "confirm",
|
|
485
|
+
name: "confirmed",
|
|
486
|
+
message: `Install the React Grab skill (${global ? "global" : "this project"})?`,
|
|
487
|
+
initial: true
|
|
488
|
+
});
|
|
489
|
+
if (!confirmed) return false;
|
|
437
490
|
const { agents } = await prompts({
|
|
438
491
|
type: "multiselect",
|
|
439
492
|
name: "agents",
|
|
@@ -484,7 +537,7 @@ const removeSkill = async ({ cwd = process.cwd(), global = false } = {}) => {
|
|
|
484
537
|
};
|
|
485
538
|
//#endregion
|
|
486
539
|
//#region src/commands/add.ts
|
|
487
|
-
const VERSION$5 = "0.1.
|
|
540
|
+
const VERSION$5 = "0.1.44-dev.099016d";
|
|
488
541
|
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()).option("-g, --global", "install the skill globally instead of in the project", false).action(async (opts) => {
|
|
489
542
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$5)}`);
|
|
490
543
|
console.log();
|
|
@@ -639,80 +692,14 @@ const TANSTACK_EFFECT = `useEffect(() => {
|
|
|
639
692
|
const SCRIPT_IMPORT = "import Script from \"next/script\";";
|
|
640
693
|
//#endregion
|
|
641
694
|
//#region src/utils/transform.ts
|
|
642
|
-
const hasReactGrabCode = (content) => {
|
|
643
|
-
return [
|
|
644
|
-
/["'`][^"'`]*react-grab/,
|
|
645
|
-
/react-grab[^"'`]*["'`]/,
|
|
646
|
-
/<[^>]*react-grab/i,
|
|
647
|
-
/import[^;]*react-grab/i,
|
|
648
|
-
/require[^)]*react-grab/i,
|
|
649
|
-
/from\s+[^;]*react-grab/i,
|
|
650
|
-
/src[^>]*react-grab/i,
|
|
651
|
-
/href[^>]*react-grab/i
|
|
652
|
-
].some((pattern) => pattern.test(content));
|
|
653
|
-
};
|
|
654
|
-
const findLayoutFile = (projectRoot) => {
|
|
655
|
-
const possiblePaths = [
|
|
656
|
-
join(projectRoot, "app", "layout.tsx"),
|
|
657
|
-
join(projectRoot, "app", "layout.jsx"),
|
|
658
|
-
join(projectRoot, "src", "app", "layout.tsx"),
|
|
659
|
-
join(projectRoot, "src", "app", "layout.jsx")
|
|
660
|
-
];
|
|
661
|
-
for (const filePath of possiblePaths) if (existsSync(filePath)) return filePath;
|
|
662
|
-
return null;
|
|
663
|
-
};
|
|
664
|
-
const findInstrumentationFile = (projectRoot) => {
|
|
665
|
-
const possiblePaths = [
|
|
666
|
-
join(projectRoot, "instrumentation-client.ts"),
|
|
667
|
-
join(projectRoot, "instrumentation-client.js"),
|
|
668
|
-
join(projectRoot, "src", "instrumentation-client.ts"),
|
|
669
|
-
join(projectRoot, "src", "instrumentation-client.js")
|
|
670
|
-
];
|
|
671
|
-
for (const filePath of possiblePaths) if (existsSync(filePath)) return filePath;
|
|
672
|
-
return null;
|
|
673
|
-
};
|
|
674
695
|
const hasReactGrabInInstrumentation = (projectRoot) => {
|
|
675
|
-
|
|
676
|
-
if (!instrumentationPath) return false;
|
|
677
|
-
return hasReactGrabCode(readFileSync(instrumentationPath, "utf-8"));
|
|
678
|
-
};
|
|
679
|
-
const findDocumentFile = (projectRoot) => {
|
|
680
|
-
const possiblePaths = [
|
|
681
|
-
join(projectRoot, "pages", "_document.tsx"),
|
|
682
|
-
join(projectRoot, "pages", "_document.jsx"),
|
|
683
|
-
join(projectRoot, "src", "pages", "_document.tsx"),
|
|
684
|
-
join(projectRoot, "src", "pages", "_document.jsx")
|
|
685
|
-
];
|
|
686
|
-
for (const filePath of possiblePaths) if (existsSync(filePath)) return filePath;
|
|
687
|
-
return null;
|
|
696
|
+
return findFileWithReactGrabSetup(getInstrumentationFileCandidates(projectRoot)) !== null;
|
|
688
697
|
};
|
|
689
|
-
const
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
const findEntryFile = (projectRoot) => {
|
|
695
|
-
const possiblePaths = [
|
|
696
|
-
join(projectRoot, "src", "index.tsx"),
|
|
697
|
-
join(projectRoot, "src", "index.jsx"),
|
|
698
|
-
join(projectRoot, "src", "index.ts"),
|
|
699
|
-
join(projectRoot, "src", "index.js"),
|
|
700
|
-
join(projectRoot, "src", "main.tsx"),
|
|
701
|
-
join(projectRoot, "src", "main.jsx"),
|
|
702
|
-
join(projectRoot, "src", "main.ts"),
|
|
703
|
-
join(projectRoot, "src", "main.js")
|
|
704
|
-
];
|
|
705
|
-
for (const filePath of possiblePaths) if (existsSync(filePath)) return filePath;
|
|
706
|
-
return null;
|
|
707
|
-
};
|
|
708
|
-
const findTanStackRootFile = (projectRoot) => {
|
|
709
|
-
const possiblePaths = [
|
|
710
|
-
join(projectRoot, "src", "routes", "__root.tsx"),
|
|
711
|
-
join(projectRoot, "src", "routes", "__root.jsx"),
|
|
712
|
-
join(projectRoot, "app", "routes", "__root.tsx"),
|
|
713
|
-
join(projectRoot, "app", "routes", "__root.jsx")
|
|
714
|
-
];
|
|
715
|
-
for (const filePath of possiblePaths) if (existsSync(filePath)) return filePath;
|
|
698
|
+
const findFileWithReactGrabSetup = (fileCandidates) => {
|
|
699
|
+
for (const filePath of fileCandidates) {
|
|
700
|
+
if (!existsSync(filePath)) continue;
|
|
701
|
+
if (hasReactGrabSetupCode(readFileSync(filePath, "utf-8"))) return filePath;
|
|
702
|
+
}
|
|
716
703
|
return null;
|
|
717
704
|
};
|
|
718
705
|
const alreadyConfiguredResult = (filePath) => ({
|
|
@@ -721,19 +708,19 @@ const alreadyConfiguredResult = (filePath) => ({
|
|
|
721
708
|
message: "React Grab is already configured",
|
|
722
709
|
noChanges: true
|
|
723
710
|
});
|
|
724
|
-
const transformNextAppRouter = (projectRoot, reactGrabAlreadyConfigured
|
|
711
|
+
const transformNextAppRouter = (projectRoot, reactGrabAlreadyConfigured) => {
|
|
725
712
|
const layoutPath = findLayoutFile(projectRoot);
|
|
726
713
|
if (!layoutPath) return {
|
|
727
714
|
success: false,
|
|
728
715
|
filePath: "",
|
|
729
|
-
message: "Could not find app/layout.tsx or app/layout.
|
|
716
|
+
message: "Could not find app/layout.tsx, app/layout.jsx, app/layout.ts, or app/layout.js"
|
|
730
717
|
};
|
|
731
718
|
const originalContent = readFileSync(layoutPath, "utf-8");
|
|
732
719
|
let newContent = originalContent;
|
|
733
|
-
const hasReactGrabInFile =
|
|
720
|
+
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
|
734
721
|
const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
|
|
735
|
-
if (
|
|
736
|
-
if (
|
|
722
|
+
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(layoutPath);
|
|
723
|
+
if (hasReactGrabInFile || hasReactGrabInInstrumentationFile) return {
|
|
737
724
|
success: true,
|
|
738
725
|
filePath: layoutPath,
|
|
739
726
|
message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
|
|
@@ -758,19 +745,19 @@ const transformNextAppRouter = (projectRoot, reactGrabAlreadyConfigured, force =
|
|
|
758
745
|
newContent
|
|
759
746
|
};
|
|
760
747
|
};
|
|
761
|
-
const transformNextPagesRouter = (projectRoot, reactGrabAlreadyConfigured
|
|
748
|
+
const transformNextPagesRouter = (projectRoot, reactGrabAlreadyConfigured) => {
|
|
762
749
|
const documentPath = findDocumentFile(projectRoot);
|
|
763
750
|
if (!documentPath) return {
|
|
764
751
|
success: false,
|
|
765
752
|
filePath: "",
|
|
766
|
-
message: "Could not find pages/_document.tsx or pages/_document.
|
|
753
|
+
message: "Could not find pages/_document.tsx, pages/_document.jsx, pages/_document.ts, or pages/_document.js.\n\nTo set up React Grab with Pages Router, create pages/_document.tsx with:\n\n import { Html, Head, Main, NextScript } from \"next/document\";\n import Script from \"next/script\";\n\n export default function Document() {\n return (\n <Html>\n <Head>\n {process.env.NODE_ENV === \"development\" && (\n <Script src=\"//unpkg.com/react-grab/dist/index.global.js\" strategy=\"beforeInteractive\" />\n )}\n </Head>\n <body>\n <Main />\n <NextScript />\n </body>\n </Html>\n );\n }"
|
|
767
754
|
};
|
|
768
755
|
const originalContent = readFileSync(documentPath, "utf-8");
|
|
769
756
|
let newContent = originalContent;
|
|
770
|
-
const hasReactGrabInFile =
|
|
757
|
+
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
|
771
758
|
const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
|
|
772
|
-
if (
|
|
773
|
-
if (
|
|
759
|
+
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(documentPath);
|
|
760
|
+
if (hasReactGrabInFile || hasReactGrabInInstrumentationFile) return {
|
|
774
761
|
success: true,
|
|
775
762
|
filePath: documentPath,
|
|
776
763
|
message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
|
|
@@ -791,7 +778,7 @@ const transformNextPagesRouter = (projectRoot, reactGrabAlreadyConfigured, force
|
|
|
791
778
|
};
|
|
792
779
|
};
|
|
793
780
|
const checkExistingInstallation = (filePath, reactGrabAlreadyConfigured) => {
|
|
794
|
-
if (!
|
|
781
|
+
if (!hasReactGrabSetupCode(readFileSync(filePath, "utf-8"))) return null;
|
|
795
782
|
return {
|
|
796
783
|
success: true,
|
|
797
784
|
filePath,
|
|
@@ -799,24 +786,20 @@ const checkExistingInstallation = (filePath, reactGrabAlreadyConfigured) => {
|
|
|
799
786
|
noChanges: true
|
|
800
787
|
};
|
|
801
788
|
};
|
|
802
|
-
const transformVite = (projectRoot, reactGrabAlreadyConfigured
|
|
789
|
+
const transformVite = (projectRoot, reactGrabAlreadyConfigured) => {
|
|
803
790
|
const entryPath = findEntryFile(projectRoot);
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (existingResult) return existingResult;
|
|
809
|
-
}
|
|
791
|
+
const indexPath = findIndexHtml(projectRoot);
|
|
792
|
+
if (indexPath) {
|
|
793
|
+
const existingResult = checkExistingInstallation(indexPath, reactGrabAlreadyConfigured);
|
|
794
|
+
if (existingResult) return existingResult;
|
|
810
795
|
}
|
|
811
796
|
if (!entryPath) return {
|
|
812
797
|
success: false,
|
|
813
798
|
filePath: "",
|
|
814
799
|
message: "Could not find entry file (src/index.tsx, src/main.tsx, etc.)"
|
|
815
800
|
};
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
if (existingResult) return existingResult;
|
|
819
|
-
}
|
|
801
|
+
const existingResult = checkExistingInstallation(entryPath, reactGrabAlreadyConfigured);
|
|
802
|
+
if (existingResult) return existingResult;
|
|
820
803
|
const originalContent = readFileSync(entryPath, "utf-8");
|
|
821
804
|
return {
|
|
822
805
|
success: true,
|
|
@@ -826,17 +809,15 @@ const transformVite = (projectRoot, reactGrabAlreadyConfigured, force = false) =
|
|
|
826
809
|
newContent: `${VITE_IMPORT}\n\n${originalContent}`
|
|
827
810
|
};
|
|
828
811
|
};
|
|
829
|
-
const transformWebpack = (projectRoot, reactGrabAlreadyConfigured
|
|
812
|
+
const transformWebpack = (projectRoot, reactGrabAlreadyConfigured) => {
|
|
830
813
|
const entryPath = findEntryFile(projectRoot);
|
|
831
814
|
if (!entryPath) return {
|
|
832
815
|
success: false,
|
|
833
816
|
filePath: "",
|
|
834
817
|
message: "Could not find entry file (src/index.tsx, src/main.tsx, etc.)"
|
|
835
818
|
};
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (existingResult) return existingResult;
|
|
839
|
-
}
|
|
819
|
+
const existingResult = checkExistingInstallation(entryPath, reactGrabAlreadyConfigured);
|
|
820
|
+
if (existingResult) return existingResult;
|
|
840
821
|
const originalContent = readFileSync(entryPath, "utf-8");
|
|
841
822
|
return {
|
|
842
823
|
success: true,
|
|
@@ -846,7 +827,7 @@ const transformWebpack = (projectRoot, reactGrabAlreadyConfigured, force = false
|
|
|
846
827
|
newContent: `${WEBPACK_IMPORT}\n\n${originalContent}`
|
|
847
828
|
};
|
|
848
829
|
};
|
|
849
|
-
const transformTanStack = (projectRoot, reactGrabAlreadyConfigured
|
|
830
|
+
const transformTanStack = (projectRoot, reactGrabAlreadyConfigured) => {
|
|
850
831
|
const rootPath = findTanStackRootFile(projectRoot);
|
|
851
832
|
if (!rootPath) return {
|
|
852
833
|
success: false,
|
|
@@ -855,9 +836,9 @@ const transformTanStack = (projectRoot, reactGrabAlreadyConfigured, force = fals
|
|
|
855
836
|
};
|
|
856
837
|
const originalContent = readFileSync(rootPath, "utf-8");
|
|
857
838
|
let newContent = originalContent;
|
|
858
|
-
const hasReactGrabInFile =
|
|
859
|
-
if (
|
|
860
|
-
if (
|
|
839
|
+
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
|
840
|
+
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(rootPath);
|
|
841
|
+
if (hasReactGrabInFile) return {
|
|
861
842
|
success: true,
|
|
862
843
|
filePath: rootPath,
|
|
863
844
|
message: "React Grab is already installed in this file",
|
|
@@ -900,14 +881,14 @@ const hasFrameworkEntryPoint = (projectRoot, framework, nextRouterType) => {
|
|
|
900
881
|
default: return false;
|
|
901
882
|
}
|
|
902
883
|
};
|
|
903
|
-
const previewTransform = (projectRoot, framework, nextRouterType, reactGrabAlreadyConfigured = false
|
|
884
|
+
const previewTransform = (projectRoot, framework, nextRouterType, reactGrabAlreadyConfigured = false) => {
|
|
904
885
|
switch (framework) {
|
|
905
886
|
case "next":
|
|
906
|
-
if (nextRouterType === "app") return transformNextAppRouter(projectRoot, reactGrabAlreadyConfigured
|
|
907
|
-
return transformNextPagesRouter(projectRoot, reactGrabAlreadyConfigured
|
|
908
|
-
case "vite": return transformVite(projectRoot, reactGrabAlreadyConfigured
|
|
909
|
-
case "tanstack": return transformTanStack(projectRoot, reactGrabAlreadyConfigured
|
|
910
|
-
case "webpack": return transformWebpack(projectRoot, reactGrabAlreadyConfigured
|
|
887
|
+
if (nextRouterType === "app") return transformNextAppRouter(projectRoot, reactGrabAlreadyConfigured);
|
|
888
|
+
return transformNextPagesRouter(projectRoot, reactGrabAlreadyConfigured);
|
|
889
|
+
case "vite": return transformVite(projectRoot, reactGrabAlreadyConfigured);
|
|
890
|
+
case "tanstack": return transformTanStack(projectRoot, reactGrabAlreadyConfigured);
|
|
891
|
+
case "webpack": return transformWebpack(projectRoot, reactGrabAlreadyConfigured);
|
|
911
892
|
default: return {
|
|
912
893
|
success: false,
|
|
913
894
|
filePath: "",
|
|
@@ -961,18 +942,24 @@ const formatOptionsAsJson = (options) => {
|
|
|
961
942
|
};
|
|
962
943
|
const findReactGrabFile = (projectRoot, framework, nextRouterType) => {
|
|
963
944
|
switch (framework) {
|
|
964
|
-
case "next":
|
|
965
|
-
|
|
966
|
-
|
|
945
|
+
case "next": {
|
|
946
|
+
const primaryFile = nextRouterType === "app" ? findLayoutFile(projectRoot) : findDocumentFile(projectRoot);
|
|
947
|
+
const primarySetupFile = findFileWithReactGrabSetup(nextRouterType === "app" ? getLayoutFileCandidates(projectRoot) : getDocumentFileCandidates(projectRoot));
|
|
948
|
+
if (primarySetupFile) return primarySetupFile;
|
|
949
|
+
const instrumentationFile = findFileWithReactGrabSetup(getInstrumentationFileCandidates(projectRoot));
|
|
950
|
+
if (instrumentationFile) return instrumentationFile;
|
|
951
|
+
return primaryFile;
|
|
952
|
+
}
|
|
967
953
|
case "vite": {
|
|
968
954
|
const entryFile = findEntryFile(projectRoot);
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
955
|
+
const entrySetupFile = findFileWithReactGrabSetup(getEntryFileCandidates(projectRoot));
|
|
956
|
+
if (entrySetupFile) return entrySetupFile;
|
|
957
|
+
const indexHtml = findFileWithReactGrabSetup(getIndexHtmlCandidates(projectRoot));
|
|
958
|
+
if (indexHtml) return indexHtml;
|
|
972
959
|
return entryFile;
|
|
973
960
|
}
|
|
974
|
-
case "tanstack": return findTanStackRootFile(projectRoot);
|
|
975
|
-
case "webpack": return findEntryFile(projectRoot);
|
|
961
|
+
case "tanstack": return findFileWithReactGrabSetup(getTanStackRootFileCandidates(projectRoot)) ?? findTanStackRootFile(projectRoot);
|
|
962
|
+
case "webpack": return findFileWithReactGrabSetup(getEntryFileCandidates(projectRoot)) ?? findEntryFile(projectRoot);
|
|
976
963
|
default: return null;
|
|
977
964
|
}
|
|
978
965
|
};
|
|
@@ -1000,13 +987,14 @@ const addOptionsToNextScript = (originalContent, options, filePath) => {
|
|
|
1000
987
|
};
|
|
1001
988
|
};
|
|
1002
989
|
const addOptionsToDynamicImport = (originalContent, options, filePath) => {
|
|
1003
|
-
const reactGrabImportWithInitMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\)(?:\.then\s*\(\s
|
|
990
|
+
const reactGrabImportWithInitMatch = originalContent.match(/(void\s+)?import\s*\(\s*["']react-grab(?:\/[^"']+)?["']\s*\)(?:\.then\s*\(\s*(?:\(m\)\s*=>\s*m\.init\s*\([^)]*\)|\(\{\s*init\s*\}\)\s*=>\s*init\s*\([^)]*\))\s*\))?/);
|
|
1004
991
|
if (!reactGrabImportWithInitMatch) return {
|
|
1005
992
|
success: false,
|
|
1006
993
|
filePath,
|
|
1007
994
|
message: "Could not find React Grab import"
|
|
1008
995
|
};
|
|
1009
|
-
const
|
|
996
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
997
|
+
const newImport = `${reactGrabImportWithInitMatch[1] ?? ""}import("react-grab").then((m) => m.init(${optionsJson}))`;
|
|
1010
998
|
return {
|
|
1011
999
|
success: true,
|
|
1012
1000
|
filePath,
|
|
@@ -1016,13 +1004,14 @@ const addOptionsToDynamicImport = (originalContent, options, filePath) => {
|
|
|
1016
1004
|
};
|
|
1017
1005
|
};
|
|
1018
1006
|
const addOptionsToTanStackImport = (originalContent, options, filePath) => {
|
|
1019
|
-
const reactGrabImportWithInitMatch = originalContent.match(/(?:void\s+
|
|
1007
|
+
const reactGrabImportWithInitMatch = originalContent.match(/(?:(void\s+)?import\s*\(\s*["']react-grab\/core["']\s*\)\.then\s*\(\s*(?:\(\s*\{\s*init\s*\}\s*\)\s*=>\s*init\s*\([^)]*\)|\(m\)\s*=>\s*m\.init\s*\([^)]*\))\s*\)|(void\s+)?import\s*\(\s*["']react-grab(?!\/core)(?:\/[^"']+)?["']\s*\))/);
|
|
1020
1008
|
if (!reactGrabImportWithInitMatch) return {
|
|
1021
1009
|
success: false,
|
|
1022
1010
|
filePath,
|
|
1023
1011
|
message: "Could not find React Grab import"
|
|
1024
1012
|
};
|
|
1025
|
-
const
|
|
1013
|
+
const optionsJson = formatOptionsAsJson(options);
|
|
1014
|
+
const newImport = `${reactGrabImportWithInitMatch[1] ?? reactGrabImportWithInitMatch[2] ?? ""}import("react-grab/core").then(({ init }) => init(${optionsJson}))`;
|
|
1026
1015
|
return {
|
|
1027
1016
|
success: true,
|
|
1028
1017
|
filePath,
|
|
@@ -1031,6 +1020,11 @@ const addOptionsToTanStackImport = (originalContent, options, filePath) => {
|
|
|
1031
1020
|
newContent: originalContent.replace(reactGrabImportWithInitMatch[0], newImport)
|
|
1032
1021
|
};
|
|
1033
1022
|
};
|
|
1023
|
+
const addOptionsToAnyImport = (originalContent, options, filePath) => {
|
|
1024
|
+
const dynamicImportResult = addOptionsToDynamicImport(originalContent, options, filePath);
|
|
1025
|
+
if (dynamicImportResult.success) return dynamicImportResult;
|
|
1026
|
+
return addOptionsToTanStackImport(originalContent, options, filePath);
|
|
1027
|
+
};
|
|
1034
1028
|
const previewOptionsTransform = (projectRoot, framework, nextRouterType, options) => {
|
|
1035
1029
|
const filePath = findReactGrabFile(projectRoot, framework, nextRouterType);
|
|
1036
1030
|
if (!filePath) return {
|
|
@@ -1039,13 +1033,15 @@ const previewOptionsTransform = (projectRoot, framework, nextRouterType, options
|
|
|
1039
1033
|
message: "Could not find file containing React Grab configuration"
|
|
1040
1034
|
};
|
|
1041
1035
|
const originalContent = readFileSync(filePath, "utf-8");
|
|
1042
|
-
if (!
|
|
1036
|
+
if (!hasReactGrabSetupCode(originalContent)) return {
|
|
1043
1037
|
success: false,
|
|
1044
1038
|
filePath,
|
|
1045
1039
|
message: "Could not find React Grab code in the file"
|
|
1046
1040
|
};
|
|
1047
1041
|
switch (framework) {
|
|
1048
|
-
case "next":
|
|
1042
|
+
case "next":
|
|
1043
|
+
if (isInstrumentationFile(filePath)) return addOptionsToAnyImport(originalContent, options, filePath);
|
|
1044
|
+
return addOptionsToNextScript(originalContent, options, filePath);
|
|
1049
1045
|
case "vite": return addOptionsToDynamicImport(originalContent, options, filePath);
|
|
1050
1046
|
case "tanstack": return addOptionsToTanStackImport(originalContent, options, filePath);
|
|
1051
1047
|
case "webpack": return addOptionsToDynamicImport(originalContent, options, filePath);
|
|
@@ -1103,7 +1099,7 @@ const formatActivationKeyDisplay = (activationKey) => {
|
|
|
1103
1099
|
};
|
|
1104
1100
|
//#endregion
|
|
1105
1101
|
//#region src/commands/configure.ts
|
|
1106
|
-
const VERSION$4 = "0.1.
|
|
1102
|
+
const VERSION$4 = "0.1.44-dev.099016d";
|
|
1107
1103
|
const isMac = process.platform === "darwin";
|
|
1108
1104
|
const META_LABEL = isMac ? "Cmd" : "Win";
|
|
1109
1105
|
const ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -1373,8 +1369,8 @@ const generateSuggestions = (input) => {
|
|
|
1373
1369
|
const CONFIG_OPTIONS = [
|
|
1374
1370
|
{
|
|
1375
1371
|
id: "activationKey",
|
|
1376
|
-
title: "
|
|
1377
|
-
description: "The
|
|
1372
|
+
title: "Shortcut",
|
|
1373
|
+
description: "The shortcut used to activate React Grab (e.g., g, k, space)"
|
|
1378
1374
|
},
|
|
1379
1375
|
{
|
|
1380
1376
|
id: "activationMode",
|
|
@@ -1409,7 +1405,7 @@ const comboToString = (combo) => {
|
|
|
1409
1405
|
}
|
|
1410
1406
|
return parts.join("+");
|
|
1411
1407
|
};
|
|
1412
|
-
const configure = new Command().name("configure").alias("config").description("configure React Grab options").option("-y, --yes", "skip confirmation prompts", false).option("-k, --key <key>", "
|
|
1408
|
+
const configure = new Command().name("configure").alias("config").description("configure React Grab options").option("-y, --yes", "skip confirmation prompts", false).option("-k, --key <key>", "shortcut (e.g., Meta+K, Ctrl+Shift+G, Space)").option("-m, --mode <mode>", "activation mode (toggle, hold)").option("--hold-duration <ms>", "key hold duration in milliseconds (for hold mode)").option("--allow-input <boolean>", "allow activation inside input fields (true/false)").option("--context-lines <lines>", "max context lines to include").option("--cdn <domain>", "CDN domain (e.g., unpkg.com, custom.react-grab.com)").option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
1413
1409
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$4)}`);
|
|
1414
1410
|
console.log();
|
|
1415
1411
|
try {
|
|
@@ -1423,6 +1419,13 @@ const configure = new Command().name("configure").alias("config").description("c
|
|
|
1423
1419
|
logger.break();
|
|
1424
1420
|
process.exit(1);
|
|
1425
1421
|
}
|
|
1422
|
+
if (!projectInfo.isReactGrabConfigured) {
|
|
1423
|
+
preflightSpinner.fail("React Grab is installed, but setup is missing.");
|
|
1424
|
+
logger.break();
|
|
1425
|
+
logger.error(`Run ${highlighter.info("react-grab init")} to add the setup script/import before configuring options.`);
|
|
1426
|
+
logger.break();
|
|
1427
|
+
process.exit(1);
|
|
1428
|
+
}
|
|
1426
1429
|
preflightSpinner.succeed();
|
|
1427
1430
|
if (opts.cdn) {
|
|
1428
1431
|
const result = previewCdnTransform(projectInfo.projectRoot, projectInfo.framework, projectInfo.nextRouterType, opts.cdn);
|
|
@@ -1478,7 +1481,7 @@ const configure = new Command().name("configure").alias("config").description("c
|
|
|
1478
1481
|
if (hasFlags) {
|
|
1479
1482
|
if (opts.key) {
|
|
1480
1483
|
collectedOptions.activationKey = opts.key;
|
|
1481
|
-
logger.log(`
|
|
1484
|
+
logger.log(` Shortcut: ${highlighter.info(formatActivationKeyDisplay(collectedOptions.activationKey))}`);
|
|
1482
1485
|
}
|
|
1483
1486
|
if (opts.mode) {
|
|
1484
1487
|
if (opts.mode !== "toggle" && opts.mode !== "hold") {
|
|
@@ -1543,7 +1546,7 @@ const configure = new Command().name("configure").alias("config").description("c
|
|
|
1543
1546
|
process.exit(1);
|
|
1544
1547
|
}
|
|
1545
1548
|
collectedOptions.activationKey = comboToString(selectedCombo);
|
|
1546
|
-
logger.log(`
|
|
1549
|
+
logger.log(` Shortcut: ${highlighter.info(formatActivationKeyDisplay(collectedOptions.activationKey))}`);
|
|
1547
1550
|
}
|
|
1548
1551
|
if (selectedOption === "activationMode") {
|
|
1549
1552
|
const { activationMode } = await prompts({
|
|
@@ -1728,7 +1731,7 @@ const isTelemetryEnabled = () => {
|
|
|
1728
1731
|
};
|
|
1729
1732
|
//#endregion
|
|
1730
1733
|
//#region src/commands/init.ts
|
|
1731
|
-
const VERSION$3 = "0.1.
|
|
1734
|
+
const VERSION$3 = "0.1.44-dev.099016d";
|
|
1732
1735
|
const REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
1733
1736
|
const DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
1734
1737
|
const reportToCli = (type, config, error) => {
|
|
@@ -1796,7 +1799,7 @@ const failWithManualSetup = (failingSpinner, message, { listSupportedFrameworks
|
|
|
1796
1799
|
logger.break();
|
|
1797
1800
|
process.exit(1);
|
|
1798
1801
|
};
|
|
1799
|
-
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", "
|
|
1802
|
+
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", "re-run setup checks even when React Grab is already configured", false).option("-k, --key <key>", "shortcut (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()).option("-g, --global", "install the skill globally instead of in the project", false).action(async (opts) => {
|
|
1800
1803
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$3)}`);
|
|
1801
1804
|
console.log();
|
|
1802
1805
|
try {
|
|
@@ -1810,12 +1813,12 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1810
1813
|
}
|
|
1811
1814
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
1812
1815
|
const projectInfo = await detectProject(cwd);
|
|
1813
|
-
if (projectInfo.
|
|
1816
|
+
if (projectInfo.isReactGrabConfigured && !opts.force) {
|
|
1814
1817
|
preflightSpinner.succeed();
|
|
1815
1818
|
if (isNonInteractive) {
|
|
1816
1819
|
logger.break();
|
|
1817
1820
|
logger.warn("React Grab is already installed.");
|
|
1818
|
-
logger.log(`Use ${highlighter.info("--force")} to
|
|
1821
|
+
logger.log(`Use ${highlighter.info("--force")} to re-run setup checks, or remove ${highlighter.info("--yes")} for interactive mode.`);
|
|
1819
1822
|
logger.break();
|
|
1820
1823
|
process.exit(0);
|
|
1821
1824
|
}
|
|
@@ -1839,12 +1842,12 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1839
1842
|
const collectedOptions = {};
|
|
1840
1843
|
if (opts.key) {
|
|
1841
1844
|
collectedOptions.activationKey = opts.key;
|
|
1842
|
-
logger.log(`
|
|
1845
|
+
logger.log(` Shortcut: ${highlighter.info(formatActivationKeyDisplay(collectedOptions.activationKey))}`);
|
|
1843
1846
|
} else {
|
|
1844
1847
|
const { wantActivationKey } = await prompts({
|
|
1845
1848
|
type: "confirm",
|
|
1846
1849
|
name: "wantActivationKey",
|
|
1847
|
-
message: `Configure ${highlighter.info("
|
|
1850
|
+
message: `Configure ${highlighter.info("shortcut")}?`,
|
|
1848
1851
|
initial: false
|
|
1849
1852
|
});
|
|
1850
1853
|
if (wantActivationKey === void 0) {
|
|
@@ -1855,7 +1858,7 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1855
1858
|
const { key } = await prompts({
|
|
1856
1859
|
type: "text",
|
|
1857
1860
|
name: "key",
|
|
1858
|
-
message: "Enter the
|
|
1861
|
+
message: "Enter the shortcut (e.g., g, k, space):",
|
|
1859
1862
|
initial: ""
|
|
1860
1863
|
});
|
|
1861
1864
|
if (key === void 0) {
|
|
@@ -1863,7 +1866,7 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
1863
1866
|
process.exit(1);
|
|
1864
1867
|
}
|
|
1865
1868
|
collectedOptions.activationKey = key ? key.toLowerCase() : void 0;
|
|
1866
|
-
logger.log(`
|
|
1869
|
+
logger.log(` Shortcut: ${highlighter.info(formatActivationKeyDisplay(collectedOptions.activationKey))}`);
|
|
1867
1870
|
}
|
|
1868
1871
|
}
|
|
1869
1872
|
const { activationMode } = await prompts({
|
|
@@ -2030,7 +2033,7 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
2030
2033
|
cwd
|
|
2031
2034
|
});
|
|
2032
2035
|
}
|
|
2033
|
-
const result = previewTransform(projectInfo.projectRoot, finalFramework, finalNextRouterType,
|
|
2036
|
+
const result = previewTransform(projectInfo.projectRoot, finalFramework, finalNextRouterType, projectInfo.isReactGrabConfigured);
|
|
2034
2037
|
if (!result.success) {
|
|
2035
2038
|
logger.break();
|
|
2036
2039
|
logger.error(result.message);
|
|
@@ -2065,7 +2068,8 @@ const init = new Command().name("init").alias("setup").description("initialize R
|
|
|
2065
2068
|
if (!opts.skipInstall && shouldInstallReactGrab) await installPackagesWithFeedback(getPackagesToInstall(shouldInstallReactGrab), finalPackageManager, projectInfo.projectRoot);
|
|
2066
2069
|
if (hasLayoutChanges) applyTransformWithFeedback(result);
|
|
2067
2070
|
logger.break();
|
|
2068
|
-
logger.log(`${highlighter.success("Success!")} React Grab has been installed.`);
|
|
2071
|
+
if (hasLayoutChanges) logger.log(`${highlighter.success("Success!")} React Grab has been installed.`);
|
|
2072
|
+
else logger.log(`${highlighter.success("Success!")} ${result.message}.`);
|
|
2069
2073
|
logger.log("You may now start your development server.");
|
|
2070
2074
|
logger.break();
|
|
2071
2075
|
reportToCli("completed", {
|
|
@@ -2678,7 +2682,7 @@ const pull = new Command().name("pull").description("start the watcher if needed
|
|
|
2678
2682
|
});
|
|
2679
2683
|
//#endregion
|
|
2680
2684
|
//#region src/commands/remove.ts
|
|
2681
|
-
const VERSION$2 = "0.1.
|
|
2685
|
+
const VERSION$2 = "0.1.44-dev.099016d";
|
|
2682
2686
|
const remove = new Command().name("remove").description("uninstall the React Grab skill from your agent").option("-c, --cwd <cwd>", "working directory (defaults to current directory)", process.cwd()).option("-g, --global", "remove the globally-installed skill instead of the project's", false).action(async (opts) => {
|
|
2683
2687
|
console.log(`${pc.magenta("✿")} ${pc.bold("React Grab")} ${pc.gray(VERSION$2)}`);
|
|
2684
2688
|
console.log();
|
|
@@ -2706,7 +2710,7 @@ const stop = new Command().name("stop").description("stop the React Grab watcher
|
|
|
2706
2710
|
});
|
|
2707
2711
|
//#endregion
|
|
2708
2712
|
//#region src/commands/upgrade.ts
|
|
2709
|
-
const VERSION$1 = "0.1.
|
|
2713
|
+
const VERSION$1 = "0.1.44-dev.099016d";
|
|
2710
2714
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org/react-grab/latest";
|
|
2711
2715
|
const fetchLatestVersion = async () => {
|
|
2712
2716
|
try {
|
|
@@ -2818,7 +2822,7 @@ const watch = new Command().name("watch").description("run the React Grab captur
|
|
|
2818
2822
|
});
|
|
2819
2823
|
//#endregion
|
|
2820
2824
|
//#region src/cli.ts
|
|
2821
|
-
const VERSION = "0.1.
|
|
2825
|
+
const VERSION = "0.1.44-dev.099016d";
|
|
2822
2826
|
const VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
2823
2827
|
process.on("SIGINT", () => process.exit(0));
|
|
2824
2828
|
process.on("SIGTERM", () => process.exit(0));
|