fix(mobile): resolve user avatars, chat alignment, timestamp formatting, and payslips API
This commit is contained in:
70
node_modules/@react-grab/cli/dist/api.cjs
generated
vendored
Normal file
70
node_modules/@react-grab/cli/dist/api.cjs
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env node
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const require_install = require("./install-DlD3sLtm.cjs");
|
||||
let node_path = require("node:path");
|
||||
//#region src/utils/install-react-grab.ts
|
||||
var ReactGrabInstallError = class extends Error {
|
||||
code;
|
||||
constructor(message, code, options) {
|
||||
super(message, options);
|
||||
this.name = "ReactGrabInstallError";
|
||||
this.code = code;
|
||||
}
|
||||
};
|
||||
const installReactGrab = async (options = {}) => {
|
||||
const project = await require_install.detectProject((0, node_path.resolve)(options.cwd ?? process.cwd()));
|
||||
const framework = options.framework ?? project.framework;
|
||||
const packageManager = options.packageManager ?? project.packageManager;
|
||||
if (project.unsupportedFramework && !options.framework) throw new ReactGrabInstallError(`${project.unsupportedFramework} is not supported by automatic setup.`, "unsupported-framework");
|
||||
if (framework === "unknown") throw new ReactGrabInstallError("Could not detect a supported framework. Pass `framework` explicitly to override detection.", "unknown-framework");
|
||||
const nextRouterType = options.nextRouterType ?? (framework === "next" && project.nextRouterType === "unknown" ? require_install.detectNextRouterType(project.projectRoot) : project.nextRouterType);
|
||||
const alreadyConfigured = project.isReactGrabConfigured;
|
||||
const transform = require_install.previewTransform(project.projectRoot, framework, nextRouterType, alreadyConfigured);
|
||||
if (!transform.success && !options.skipTransform) throw new ReactGrabInstallError(transform.message, "transform-failed");
|
||||
const didInstallPackage = !options.skipPackageInstall && !options.dryRun && !project.hasReactGrab;
|
||||
if (didInstallPackage) try {
|
||||
await require_install.installPackages(require_install.getPackagesToInstall(), {
|
||||
...options.installPackageOptions,
|
||||
cwd: project.projectRoot,
|
||||
packageManager
|
||||
});
|
||||
} catch (error) {
|
||||
throw new ReactGrabInstallError(error instanceof Error ? error.message : "Failed to install the react-grab package.", "install-failed", { cause: error });
|
||||
}
|
||||
const didChangeFile = !transform.noChanges && Boolean(transform.newContent) && !options.skipTransform && !options.dryRun;
|
||||
if (didChangeFile) {
|
||||
const writeResult = require_install.applyTransform(transform);
|
||||
if (!writeResult.success) throw new ReactGrabInstallError(writeResult.error ?? `Failed to write to ${transform.filePath}`, "write-failed");
|
||||
}
|
||||
return {
|
||||
projectRoot: project.projectRoot,
|
||||
framework,
|
||||
nextRouterType,
|
||||
packageManager,
|
||||
alreadyConfigured,
|
||||
didInstallPackage,
|
||||
didChangeFile,
|
||||
dryRun: Boolean(options.dryRun),
|
||||
transform
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
exports.ReactGrabInstallError = ReactGrabInstallError;
|
||||
exports.applyTransform = require_install.applyTransform;
|
||||
exports.detectFramework = require_install.detectFramework;
|
||||
exports.detectNextRouterType = require_install.detectNextRouterType;
|
||||
exports.detectPackageManager = require_install.detectPackageManager;
|
||||
exports.detectProject = require_install.detectProject;
|
||||
exports.detectReactGrab = require_install.detectReactGrab;
|
||||
exports.detectReactGrabConfigured = require_install.detectReactGrabConfigured;
|
||||
exports.detectUnsupportedFramework = require_install.detectUnsupportedFramework;
|
||||
exports.findReactProjects = require_install.findReactProjects;
|
||||
exports.getPackagesToInstall = require_install.getPackagesToInstall;
|
||||
exports.hasFrameworkEntryPoint = require_install.hasFrameworkEntryPoint;
|
||||
exports.installPackages = require_install.installPackages;
|
||||
exports.installReactGrab = installReactGrab;
|
||||
exports.installSkill = require_install.installSkill;
|
||||
exports.previewCdnTransform = require_install.previewCdnTransform;
|
||||
exports.previewOptionsTransform = require_install.previewOptionsTransform;
|
||||
exports.previewTransform = require_install.previewTransform;
|
||||
exports.removeSkill = require_install.removeSkill;
|
||||
121
node_modules/@react-grab/cli/dist/api.d.cts
generated
vendored
Normal file
121
node_modules/@react-grab/cli/dist/api.d.cts
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env node
|
||||
import { SkillAgentType, add } from "agent-install/skill";
|
||||
|
||||
//#region src/utils/detect.d.ts
|
||||
type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
|
||||
type Framework = "next" | "vite" | "tanstack" | "webpack" | "unknown";
|
||||
type NextRouterType = "app" | "pages" | "unknown";
|
||||
type UnsupportedFramework = "remix" | "astro" | "sveltekit" | "gatsby" | null;
|
||||
interface ProjectInfo {
|
||||
packageManager: PackageManager;
|
||||
framework: Framework;
|
||||
nextRouterType: NextRouterType;
|
||||
isMonorepo: boolean;
|
||||
projectRoot: string;
|
||||
hasReactGrab: boolean;
|
||||
isReactGrabConfigured: boolean;
|
||||
reactGrabVersion: string | null;
|
||||
unsupportedFramework: UnsupportedFramework;
|
||||
}
|
||||
declare const detectPackageManager: (projectRoot: string) => Promise<PackageManager>;
|
||||
declare const detectFramework: (projectRoot: string) => Framework;
|
||||
declare const detectNextRouterType: (projectRoot: string) => NextRouterType;
|
||||
interface WorkspaceProject {
|
||||
name: string;
|
||||
path: string;
|
||||
framework: Framework;
|
||||
}
|
||||
declare const findReactProjects: (projectRoot: string) => WorkspaceProject[];
|
||||
declare const detectReactGrabConfigured: (projectRoot: string) => boolean;
|
||||
declare const detectReactGrab: (projectRoot: string) => boolean;
|
||||
declare const detectUnsupportedFramework: (projectRoot: string) => UnsupportedFramework;
|
||||
declare const detectProject: (projectRoot?: string) => Promise<ProjectInfo>;
|
||||
//#endregion
|
||||
//#region src/utils/transform.d.ts
|
||||
interface TransformResult {
|
||||
success: boolean;
|
||||
filePath: string;
|
||||
message: string;
|
||||
originalContent?: string;
|
||||
newContent?: string;
|
||||
noChanges?: boolean;
|
||||
}
|
||||
interface ReactGrabOptions {
|
||||
activationKey?: string;
|
||||
activationMode?: "toggle" | "hold";
|
||||
keyHoldDuration?: number;
|
||||
allowActivationInsideInput?: boolean;
|
||||
maxContextLines?: number;
|
||||
}
|
||||
declare const hasFrameworkEntryPoint: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType) => boolean;
|
||||
declare const previewTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, reactGrabAlreadyConfigured?: boolean) => TransformResult;
|
||||
declare const applyTransform: (result: TransformResult) => {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
};
|
||||
declare const previewOptionsTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, options: ReactGrabOptions) => TransformResult;
|
||||
declare const previewCdnTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, targetCdnDomain: string) => TransformResult;
|
||||
//#endregion
|
||||
//#region src/utils/install.d.ts
|
||||
interface InstallPackageOptions {
|
||||
cwd?: string;
|
||||
isDev?: boolean;
|
||||
silent?: boolean;
|
||||
packageManager?: PackageManager;
|
||||
preferOffline?: boolean;
|
||||
additionalArgs?: string[];
|
||||
}
|
||||
declare const installPackages: (packages: string[], options?: InstallPackageOptions) => Promise<void>;
|
||||
declare const getPackagesToInstall: (includeReactGrab?: boolean) => string[];
|
||||
//#endregion
|
||||
//#region src/utils/install-react-grab.d.ts
|
||||
type ReactGrabInstallErrorCode = "unsupported-framework" | "unknown-framework" | "transform-failed" | "install-failed" | "write-failed";
|
||||
declare class ReactGrabInstallError extends Error {
|
||||
readonly code: ReactGrabInstallErrorCode;
|
||||
constructor(message: string, code: ReactGrabInstallErrorCode, options?: ErrorOptions);
|
||||
}
|
||||
interface InstallReactGrabOptions {
|
||||
cwd?: string;
|
||||
framework?: Framework;
|
||||
nextRouterType?: NextRouterType;
|
||||
packageManager?: PackageManager;
|
||||
skipPackageInstall?: boolean;
|
||||
skipTransform?: boolean;
|
||||
dryRun?: boolean;
|
||||
installPackageOptions?: Omit<InstallPackageOptions, "cwd" | "packageManager">;
|
||||
}
|
||||
interface InstallReactGrabResult {
|
||||
projectRoot: string;
|
||||
framework: Framework;
|
||||
nextRouterType: NextRouterType;
|
||||
packageManager: PackageManager;
|
||||
alreadyConfigured: boolean;
|
||||
didInstallPackage: boolean;
|
||||
didChangeFile: boolean;
|
||||
dryRun: boolean;
|
||||
transform: TransformResult;
|
||||
}
|
||||
declare const installReactGrab: (options?: InstallReactGrabOptions) => Promise<InstallReactGrabResult>;
|
||||
//#endregion
|
||||
//#region src/utils/install-skill.d.ts
|
||||
interface InstallSkillOptions {
|
||||
agents?: SkillAgentType[];
|
||||
global?: boolean;
|
||||
cwd?: string;
|
||||
}
|
||||
declare const installSkill: ({
|
||||
agents,
|
||||
global,
|
||||
cwd
|
||||
}?: InstallSkillOptions) => Promise<Awaited<ReturnType<typeof add>>>;
|
||||
interface RemoveSkillOptions {
|
||||
cwd?: string;
|
||||
global?: boolean;
|
||||
}
|
||||
declare const removeSkill: ({
|
||||
cwd,
|
||||
global
|
||||
}?: RemoveSkillOptions) => Promise<SkillAgentType[]>;
|
||||
//#endregion
|
||||
export { type Framework, type InstallPackageOptions, type InstallReactGrabOptions, type InstallReactGrabResult, type InstallSkillOptions, type NextRouterType, type PackageManager, type ProjectInfo, ReactGrabInstallError, type ReactGrabInstallErrorCode, type ReactGrabOptions, type TransformResult, type UnsupportedFramework, type WorkspaceProject, applyTransform, detectFramework, detectNextRouterType, detectPackageManager, detectProject, detectReactGrab, detectReactGrabConfigured, detectUnsupportedFramework, findReactProjects, getPackagesToInstall, hasFrameworkEntryPoint, installPackages, installReactGrab, installSkill, previewCdnTransform, previewOptionsTransform, previewTransform, removeSkill };
|
||||
//# sourceMappingURL=api.d.cts.map
|
||||
1
node_modules/@react-grab/cli/dist/api.d.cts.map
generated
vendored
Normal file
1
node_modules/@react-grab/cli/dist/api.d.cts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"api.d.cts","names":[],"sources":["../src/utils/detect.ts","../src/utils/transform.ts","../src/utils/install.ts","../src/utils/install-react-grab.ts","../src/utils/install-skill.ts"],"mappings":";;;;KAOY,cAAA;AAAA,KACA,SAAA;AAAA,KACA,cAAA;AAAA,KACA,oBAAA;AAAA,UAEK,WAAA;EACf,cAAA,EAAgB,cAAA;EAChB,SAAA,EAAW,SAAA;EACX,cAAA,EAAgB,cAAA;EAChB,UAAA;EACA,WAAA;EACA,YAAA;EACA,qBAAA;EACA,gBAAA;EACA,oBAAA,EAAsB,oBAAA;AAAA;AAAA,cAKX,oBAAA,GAA8B,WAAA,aAAsB,OAAA,CAAQ,cAAA;AAAA,cA4D5D,eAAA,GAAmB,WAAA,aAAsB,SAAA;AAAA,cAYzC,oBAAA,GAAwB,WAAA,aAAsB,cAAA;AAAA,UAyC1C,gBAAA;EACf,IAAA;EACA,IAAA;EACA,SAAA,EAAW,SAAA;AAAA;AAAA,cAqLA,iBAAA,GAAqB,WAAA,aAAsB,gBAAA;AAAA,cAuD3C,yBAAA,GAA6B,WAAA;AAAA,cAI7B,eAAA,GAAmB,WAAA;AAAA,cAGnB,0BAAA,GAA8B,WAAA,aAAsB,oBAAA;AAAA,cAqBpD,aAAA,GAAuB,WAAA,cAAsC,OAAA,CAAQ,WAAA;;;UC7XjE,eAAA;EACf,OAAA;EACA,QAAA;EACA,OAAA;EACA,eAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,gBAAA;EACf,aAAA;EACA,cAAA;EACA,eAAA;EACA,0BAAA;EACA,eAAA;AAAA;AAAA,cAgVW,sBAAA,GACX,WAAA,UACA,SAAA,EAAW,SAAA,EACX,cAAA,EAAgB,cAAA;AAAA,cAiBL,gBAAA,GACX,WAAA,UACA,SAAA,EAAW,SAAA,EACX,cAAA,EAAgB,cAAA,EAChB,0BAAA,eACC,eAAA;AAAA,cAmCU,cAAA,GAAkB,MAAA,EAAQ,eAAA;EAAoB,OAAA;EAAkB,KAAA;AAAA;AAAA,cA6OhE,uBAAA,GACX,WAAA,UACA,SAAA,EAAW,SAAA,EACX,cAAA,EAAgB,cAAA,EAChB,OAAA,EAAS,gBAAA,KACR,eAAA;AAAA,cA0CU,mBAAA,GACX,WAAA,UACA,SAAA,EAAW,SAAA,EACX,cAAA,EAAgB,cAAA,EAChB,eAAA,aACC,eAAA;;;UC/sBc,qBAAA;EACf,GAAA;EACA,KAAA;EACA,MAAA;EACA,cAAA,GAAiB,cAAA;EACjB,aAAA;EACA,cAAA;AAAA;AAAA,cAGW,eAAA,GACX,QAAA,YACA,OAAA,GAAS,qBAAA,KACR,OAAA;AAAA,cAsCU,oBAAA,GAAwB,gBAAA;;;KC5CzB,yBAAA;AAAA,cAOC,qBAAA,SAA8B,KAAA;EAAA,SAChC,IAAA,EAAM,yBAAA;cAEH,OAAA,UAAiB,IAAA,EAAM,yBAAA,EAA2B,OAAA,GAAU,YAAA;AAAA;AAAA,UAOzD,uBAAA;EACf,GAAA;EACA,SAAA,GAAY,SAAA;EACZ,cAAA,GAAiB,cAAA;EACjB,cAAA,GAAiB,cAAA;EACjB,kBAAA;EACA,aAAA;EACA,MAAA;EACA,qBAAA,GAAwB,IAAA,CAAK,qBAAA;AAAA;AAAA,UAGd,sBAAA;EACf,WAAA;EACA,SAAA,EAAW,SAAA;EACX,cAAA,EAAgB,cAAA;EAChB,cAAA,EAAgB,cAAA;EAChB,iBAAA;EACA,iBAAA;EACA,aAAA;EACA,MAAA;EACA,SAAA,EAAW,eAAA;AAAA;AAAA,cAGA,gBAAA,GACX,OAAA,GAAS,uBAAA,KACR,OAAA,CAAQ,sBAAA;;;UCtBM,mBAAA;EACf,MAAA,GAAS,cAAA;EACT,MAAA;EACA,GAAA;AAAA;AAAA,cAGW,YAAA;EAAsB,MAAA;EAAA,MAAA;EAAA;AAAA,IAIhC,mBAAA,KAA2B,OAAA,CAAQ,OAAA,CAAQ,UAAA,QAAkB,GAAA;AAAA,UAKtD,kBAAA;EACR,GAAA;EACA,MAAA;AAAA;AAAA,cAKW,WAAA;EAAqB,GAAA;EAAA;AAAA,IAG/B,kBAAA,KAA0B,OAAA,CAAQ,cAAA"}
|
||||
121
node_modules/@react-grab/cli/dist/api.d.ts
generated
vendored
Normal file
121
node_modules/@react-grab/cli/dist/api.d.ts
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env node
|
||||
import { SkillAgentType, add } from "agent-install/skill";
|
||||
|
||||
//#region src/utils/detect.d.ts
|
||||
type PackageManager = "npm" | "yarn" | "pnpm" | "bun";
|
||||
type Framework = "next" | "vite" | "tanstack" | "webpack" | "unknown";
|
||||
type NextRouterType = "app" | "pages" | "unknown";
|
||||
type UnsupportedFramework = "remix" | "astro" | "sveltekit" | "gatsby" | null;
|
||||
interface ProjectInfo {
|
||||
packageManager: PackageManager;
|
||||
framework: Framework;
|
||||
nextRouterType: NextRouterType;
|
||||
isMonorepo: boolean;
|
||||
projectRoot: string;
|
||||
hasReactGrab: boolean;
|
||||
isReactGrabConfigured: boolean;
|
||||
reactGrabVersion: string | null;
|
||||
unsupportedFramework: UnsupportedFramework;
|
||||
}
|
||||
declare const detectPackageManager: (projectRoot: string) => Promise<PackageManager>;
|
||||
declare const detectFramework: (projectRoot: string) => Framework;
|
||||
declare const detectNextRouterType: (projectRoot: string) => NextRouterType;
|
||||
interface WorkspaceProject {
|
||||
name: string;
|
||||
path: string;
|
||||
framework: Framework;
|
||||
}
|
||||
declare const findReactProjects: (projectRoot: string) => WorkspaceProject[];
|
||||
declare const detectReactGrabConfigured: (projectRoot: string) => boolean;
|
||||
declare const detectReactGrab: (projectRoot: string) => boolean;
|
||||
declare const detectUnsupportedFramework: (projectRoot: string) => UnsupportedFramework;
|
||||
declare const detectProject: (projectRoot?: string) => Promise<ProjectInfo>;
|
||||
//#endregion
|
||||
//#region src/utils/transform.d.ts
|
||||
interface TransformResult {
|
||||
success: boolean;
|
||||
filePath: string;
|
||||
message: string;
|
||||
originalContent?: string;
|
||||
newContent?: string;
|
||||
noChanges?: boolean;
|
||||
}
|
||||
interface ReactGrabOptions {
|
||||
activationKey?: string;
|
||||
activationMode?: "toggle" | "hold";
|
||||
keyHoldDuration?: number;
|
||||
allowActivationInsideInput?: boolean;
|
||||
maxContextLines?: number;
|
||||
}
|
||||
declare const hasFrameworkEntryPoint: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType) => boolean;
|
||||
declare const previewTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, reactGrabAlreadyConfigured?: boolean) => TransformResult;
|
||||
declare const applyTransform: (result: TransformResult) => {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
};
|
||||
declare const previewOptionsTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, options: ReactGrabOptions) => TransformResult;
|
||||
declare const previewCdnTransform: (projectRoot: string, framework: Framework, nextRouterType: NextRouterType, targetCdnDomain: string) => TransformResult;
|
||||
//#endregion
|
||||
//#region src/utils/install.d.ts
|
||||
interface InstallPackageOptions {
|
||||
cwd?: string;
|
||||
isDev?: boolean;
|
||||
silent?: boolean;
|
||||
packageManager?: PackageManager;
|
||||
preferOffline?: boolean;
|
||||
additionalArgs?: string[];
|
||||
}
|
||||
declare const installPackages: (packages: string[], options?: InstallPackageOptions) => Promise<void>;
|
||||
declare const getPackagesToInstall: (includeReactGrab?: boolean) => string[];
|
||||
//#endregion
|
||||
//#region src/utils/install-react-grab.d.ts
|
||||
type ReactGrabInstallErrorCode = "unsupported-framework" | "unknown-framework" | "transform-failed" | "install-failed" | "write-failed";
|
||||
declare class ReactGrabInstallError extends Error {
|
||||
readonly code: ReactGrabInstallErrorCode;
|
||||
constructor(message: string, code: ReactGrabInstallErrorCode, options?: ErrorOptions);
|
||||
}
|
||||
interface InstallReactGrabOptions {
|
||||
cwd?: string;
|
||||
framework?: Framework;
|
||||
nextRouterType?: NextRouterType;
|
||||
packageManager?: PackageManager;
|
||||
skipPackageInstall?: boolean;
|
||||
skipTransform?: boolean;
|
||||
dryRun?: boolean;
|
||||
installPackageOptions?: Omit<InstallPackageOptions, "cwd" | "packageManager">;
|
||||
}
|
||||
interface InstallReactGrabResult {
|
||||
projectRoot: string;
|
||||
framework: Framework;
|
||||
nextRouterType: NextRouterType;
|
||||
packageManager: PackageManager;
|
||||
alreadyConfigured: boolean;
|
||||
didInstallPackage: boolean;
|
||||
didChangeFile: boolean;
|
||||
dryRun: boolean;
|
||||
transform: TransformResult;
|
||||
}
|
||||
declare const installReactGrab: (options?: InstallReactGrabOptions) => Promise<InstallReactGrabResult>;
|
||||
//#endregion
|
||||
//#region src/utils/install-skill.d.ts
|
||||
interface InstallSkillOptions {
|
||||
agents?: SkillAgentType[];
|
||||
global?: boolean;
|
||||
cwd?: string;
|
||||
}
|
||||
declare const installSkill: ({
|
||||
agents,
|
||||
global,
|
||||
cwd
|
||||
}?: InstallSkillOptions) => Promise<Awaited<ReturnType<typeof add>>>;
|
||||
interface RemoveSkillOptions {
|
||||
cwd?: string;
|
||||
global?: boolean;
|
||||
}
|
||||
declare const removeSkill: ({
|
||||
cwd,
|
||||
global
|
||||
}?: RemoveSkillOptions) => Promise<SkillAgentType[]>;
|
||||
//#endregion
|
||||
export { type Framework, type InstallPackageOptions, type InstallReactGrabOptions, type InstallReactGrabResult, type InstallSkillOptions, type NextRouterType, type PackageManager, type ProjectInfo, ReactGrabInstallError, type ReactGrabInstallErrorCode, type ReactGrabOptions, type TransformResult, type UnsupportedFramework, type WorkspaceProject, applyTransform, detectFramework, detectNextRouterType, detectPackageManager, detectProject, detectReactGrab, detectReactGrabConfigured, detectUnsupportedFramework, findReactProjects, getPackagesToInstall, hasFrameworkEntryPoint, installPackages, installReactGrab, installSkill, previewCdnTransform, previewOptionsTransform, previewTransform, removeSkill };
|
||||
//# sourceMappingURL=api.d.ts.map
|
||||
1
node_modules/@react-grab/cli/dist/api.d.ts.map
generated
vendored
Normal file
1
node_modules/@react-grab/cli/dist/api.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"api.d.ts","names":[],"sources":["../src/utils/detect.ts","../src/utils/transform.ts","../src/utils/install.ts","../src/utils/install-react-grab.ts","../src/utils/install-skill.ts"],"mappings":"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"}
|
||||
53
node_modules/@react-grab/cli/dist/api.js
generated
vendored
Normal file
53
node_modules/@react-grab/cli/dist/api.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env node
|
||||
import { _ as detectReactGrabConfigured, a as previewCdnTransform, f as detectFramework, g as detectReactGrab, h as detectProject, i as hasFrameworkEntryPoint, l as installSkill, m as detectPackageManager, n as installPackages, o as previewOptionsTransform, p as detectNextRouterType, r as applyTransform, s as previewTransform, t as getPackagesToInstall, u as removeSkill, v as detectUnsupportedFramework, y as findReactProjects } from "./install-Car5vKPk.js";
|
||||
import { resolve } from "node:path";
|
||||
//#region src/utils/install-react-grab.ts
|
||||
var ReactGrabInstallError = class extends Error {
|
||||
code;
|
||||
constructor(message, code, options) {
|
||||
super(message, options);
|
||||
this.name = "ReactGrabInstallError";
|
||||
this.code = code;
|
||||
}
|
||||
};
|
||||
const installReactGrab = async (options = {}) => {
|
||||
const project = await detectProject(resolve(options.cwd ?? process.cwd()));
|
||||
const framework = options.framework ?? project.framework;
|
||||
const packageManager = options.packageManager ?? project.packageManager;
|
||||
if (project.unsupportedFramework && !options.framework) throw new ReactGrabInstallError(`${project.unsupportedFramework} is not supported by automatic setup.`, "unsupported-framework");
|
||||
if (framework === "unknown") throw new ReactGrabInstallError("Could not detect a supported framework. Pass `framework` explicitly to override detection.", "unknown-framework");
|
||||
const nextRouterType = options.nextRouterType ?? (framework === "next" && project.nextRouterType === "unknown" ? detectNextRouterType(project.projectRoot) : project.nextRouterType);
|
||||
const alreadyConfigured = project.isReactGrabConfigured;
|
||||
const transform = previewTransform(project.projectRoot, framework, nextRouterType, alreadyConfigured);
|
||||
if (!transform.success && !options.skipTransform) throw new ReactGrabInstallError(transform.message, "transform-failed");
|
||||
const didInstallPackage = !options.skipPackageInstall && !options.dryRun && !project.hasReactGrab;
|
||||
if (didInstallPackage) try {
|
||||
await installPackages(getPackagesToInstall(), {
|
||||
...options.installPackageOptions,
|
||||
cwd: project.projectRoot,
|
||||
packageManager
|
||||
});
|
||||
} catch (error) {
|
||||
throw new ReactGrabInstallError(error instanceof Error ? error.message : "Failed to install the react-grab package.", "install-failed", { cause: error });
|
||||
}
|
||||
const didChangeFile = !transform.noChanges && Boolean(transform.newContent) && !options.skipTransform && !options.dryRun;
|
||||
if (didChangeFile) {
|
||||
const writeResult = applyTransform(transform);
|
||||
if (!writeResult.success) throw new ReactGrabInstallError(writeResult.error ?? `Failed to write to ${transform.filePath}`, "write-failed");
|
||||
}
|
||||
return {
|
||||
projectRoot: project.projectRoot,
|
||||
framework,
|
||||
nextRouterType,
|
||||
packageManager,
|
||||
alreadyConfigured,
|
||||
didInstallPackage,
|
||||
didChangeFile,
|
||||
dryRun: Boolean(options.dryRun),
|
||||
transform
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
export { ReactGrabInstallError, applyTransform, detectFramework, detectNextRouterType, detectPackageManager, detectProject, detectReactGrab, detectReactGrabConfigured, detectUnsupportedFramework, findReactProjects, getPackagesToInstall, hasFrameworkEntryPoint, installPackages, installReactGrab, installSkill, previewCdnTransform, previewOptionsTransform, previewTransform, removeSkill };
|
||||
|
||||
//# sourceMappingURL=api.js.map
|
||||
1
node_modules/@react-grab/cli/dist/api.js.map
generated
vendored
Normal file
1
node_modules/@react-grab/cli/dist/api.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1986
node_modules/@react-grab/cli/dist/cli.cjs
generated
vendored
Normal file
1986
node_modules/@react-grab/cli/dist/cli.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
node_modules/@react-grab/cli/dist/cli.d.cts
generated
vendored
Normal file
2
node_modules/@react-grab/cli/dist/cli.d.cts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
export { };
|
||||
2
node_modules/@react-grab/cli/dist/cli.d.ts
generated
vendored
Normal file
2
node_modules/@react-grab/cli/dist/cli.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
export { };
|
||||
1984
node_modules/@react-grab/cli/dist/cli.js
generated
vendored
Normal file
1984
node_modules/@react-grab/cli/dist/cli.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/@react-grab/cli/dist/cli.js.map
generated
vendored
Normal file
1
node_modules/@react-grab/cli/dist/cli.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
864
node_modules/@react-grab/cli/dist/install-Car5vKPk.js
generated
vendored
Normal file
864
node_modules/@react-grab/cli/dist/install-Car5vKPk.js
generated
vendored
Normal file
@@ -0,0 +1,864 @@
|
||||
#!/usr/bin/env node
|
||||
import { basename, delimiter, dirname, join, resolve } from "node:path";
|
||||
import { accessSync, constants, existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
||||
import { detect } from "package-manager-detector/detect";
|
||||
import ignore from "ignore";
|
||||
import { add, detectInstalledSkillAgents, getCanonicalSkillsDir, getSkillAgentConfig, getSkillAgentDir, getSkillAgentTypes, isUniversalSkillAgent } from "agent-install/skill";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { x } from "tinyexec";
|
||||
//#region src/utils/react-grab-code.ts
|
||||
const REACT_GRAB_SPECIFIER_PATTERN = String.raw`react-grab(?:\/[^"']+)?`;
|
||||
const stripComments = (content) => content.replace(/<!--[\s\S]*?-->/g, "").replace(/\{\/\*[\s\S]*?\*\/\}/g, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|\s)\/\/.*$/gm, "$1");
|
||||
const stripTypeOnlyReactGrabImports = (content) => {
|
||||
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"), "");
|
||||
};
|
||||
const hasReactGrabSetupCode = (content) => {
|
||||
const setupCandidateContent = stripTypeOnlyReactGrabImports(stripComments(content));
|
||||
return [
|
||||
new RegExp(String.raw`import\s*\(\s*["']${REACT_GRAB_SPECIFIER_PATTERN}["']\s*\)`),
|
||||
new RegExp(String.raw`import\s+(?!type\b)(?:[^"';]+from\s+)?["']${REACT_GRAB_SPECIFIER_PATTERN}["']`),
|
||||
new RegExp(String.raw`require\s*\(\s*["']${REACT_GRAB_SPECIFIER_PATTERN}["']\s*\)`),
|
||||
/<Script[\s\S]*?src\s*=\s*(?:["'][^"']*react-grab[^"']*["']|\{(?:["'][^"']*react-grab[^"']*["']|`[^`]*react-grab[^`]*`)\})/i,
|
||||
/<script[\s\S]*?src\s*=\s*["'][^"']*react-grab[^"']*["']/i
|
||||
].some((pattern) => pattern.test(setupCandidateContent));
|
||||
};
|
||||
//#endregion
|
||||
//#region src/utils/react-grab-setup-files.ts
|
||||
const COMPONENT_EXTENSIONS = [
|
||||
"tsx",
|
||||
"jsx",
|
||||
"ts",
|
||||
"js"
|
||||
];
|
||||
const INSTRUMENTATION_EXTENSIONS = [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"mts",
|
||||
"cts",
|
||||
"mjs",
|
||||
"cjs"
|
||||
];
|
||||
const ROUTE_EXTENSIONS = ["tsx", "jsx"];
|
||||
const createFileCandidates = (projectRoot, directories, baseName, extensions) => {
|
||||
const fileCandidates = [];
|
||||
for (const directory of directories) for (const extension of extensions) fileCandidates.push(join(projectRoot, directory, `${baseName}.${extension}`));
|
||||
return fileCandidates;
|
||||
};
|
||||
const findExistingFile = (fileCandidates) => {
|
||||
for (const filePath of fileCandidates) if (existsSync(filePath)) return filePath;
|
||||
return null;
|
||||
};
|
||||
const getLayoutFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["app", "src/app"], "layout", COMPONENT_EXTENSIONS);
|
||||
const getDocumentFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["pages", "src/pages"], "_document", COMPONENT_EXTENSIONS);
|
||||
const getInstrumentationFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["", "src"], "instrumentation-client", INSTRUMENTATION_EXTENSIONS);
|
||||
const getIndexHtmlCandidates = (projectRoot) => [join(projectRoot, "index.html"), join(projectRoot, "public", "index.html")];
|
||||
const getEntryFileCandidates = (projectRoot) => [...createFileCandidates(projectRoot, ["src"], "index", COMPONENT_EXTENSIONS), ...createFileCandidates(projectRoot, ["src"], "main", COMPONENT_EXTENSIONS)];
|
||||
const getTanStackRootFileCandidates = (projectRoot) => createFileCandidates(projectRoot, ["src/routes", "app/routes"], "__root", ROUTE_EXTENSIONS);
|
||||
const getReactGrabSetupFileCandidates = (projectRoot) => [
|
||||
...getLayoutFileCandidates(projectRoot),
|
||||
...getDocumentFileCandidates(projectRoot),
|
||||
...getInstrumentationFileCandidates(projectRoot),
|
||||
...getIndexHtmlCandidates(projectRoot),
|
||||
...getEntryFileCandidates(projectRoot),
|
||||
...getTanStackRootFileCandidates(projectRoot)
|
||||
];
|
||||
const findLayoutFile = (projectRoot) => findExistingFile(getLayoutFileCandidates(projectRoot));
|
||||
const findDocumentFile = (projectRoot) => findExistingFile(getDocumentFileCandidates(projectRoot));
|
||||
const findIndexHtml = (projectRoot) => findExistingFile(getIndexHtmlCandidates(projectRoot));
|
||||
const findEntryFile = (projectRoot) => findExistingFile(getEntryFileCandidates(projectRoot));
|
||||
const findTanStackRootFile = (projectRoot) => findExistingFile(getTanStackRootFileCandidates(projectRoot));
|
||||
const isInstrumentationFile = (filePath) => /(?:^|[/\\])instrumentation-client\.[cm]?[jt]sx?$/.test(filePath);
|
||||
//#endregion
|
||||
//#region src/utils/detect.ts
|
||||
const VALID_PACKAGE_MANAGERS = new Set([
|
||||
"npm",
|
||||
"yarn",
|
||||
"pnpm",
|
||||
"bun"
|
||||
]);
|
||||
const detectPackageManager = async (projectRoot) => {
|
||||
const result = await detect({ cwd: projectRoot });
|
||||
if (result?.agent) {
|
||||
const managerName = result.agent.split("@")[0];
|
||||
if (VALID_PACKAGE_MANAGERS.has(managerName)) return managerName;
|
||||
}
|
||||
return "npm";
|
||||
};
|
||||
const CONFIG_EXTENSIONS = [
|
||||
"ts",
|
||||
"mts",
|
||||
"cts",
|
||||
"js",
|
||||
"mjs",
|
||||
"cjs"
|
||||
];
|
||||
const hasConfigFile = (projectRoot, configBaseName) => CONFIG_EXTENSIONS.some((extension) => existsSync(join(projectRoot, `${configBaseName}.${extension}`)));
|
||||
const readMergedDependencies = (projectRoot) => {
|
||||
const packageJsonPath = join(projectRoot, "package.json");
|
||||
if (!existsSync(packageJsonPath)) return null;
|
||||
try {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
||||
return {
|
||||
...packageJson.dependencies,
|
||||
...packageJson.devDependencies
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const detectFrameworkFromDependencies = (dependencies) => {
|
||||
if (!dependencies) return "unknown";
|
||||
if (dependencies["next"]) return "next";
|
||||
if (dependencies["@tanstack/react-start"]) return "tanstack";
|
||||
if (dependencies["vite"]) return "vite";
|
||||
if (dependencies["webpack"]) return "webpack";
|
||||
return "unknown";
|
||||
};
|
||||
const detectFrameworkFromConfigFiles = (projectRoot) => {
|
||||
if (hasConfigFile(projectRoot, "next.config")) return "next";
|
||||
if (hasConfigFile(projectRoot, "app.config")) return "tanstack";
|
||||
if (hasConfigFile(projectRoot, "vite.config")) return "vite";
|
||||
if (hasConfigFile(projectRoot, "webpack.config")) return "webpack";
|
||||
return "unknown";
|
||||
};
|
||||
const findEnclosingMonorepoRoot = (projectRoot) => {
|
||||
let currentDirectory = dirname(projectRoot);
|
||||
while (currentDirectory !== dirname(currentDirectory)) {
|
||||
if (detectMonorepo(currentDirectory)) return currentDirectory;
|
||||
currentDirectory = dirname(currentDirectory);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const detectFramework = (projectRoot) => {
|
||||
const localFramework = detectFrameworkFromDependencies(readMergedDependencies(projectRoot));
|
||||
if (localFramework !== "unknown") return localFramework;
|
||||
return detectFrameworkFromConfigFiles(projectRoot);
|
||||
};
|
||||
const detectFrameworkFromMonorepoRoot = (projectRoot) => {
|
||||
const monorepoRoot = findEnclosingMonorepoRoot(projectRoot);
|
||||
if (!monorepoRoot) return "unknown";
|
||||
return detectFrameworkFromDependencies(readMergedDependencies(monorepoRoot));
|
||||
};
|
||||
const detectNextRouterType = (projectRoot) => {
|
||||
const hasAppDir = existsSync(join(projectRoot, "app"));
|
||||
const hasSrcAppDir = existsSync(join(projectRoot, "src", "app"));
|
||||
const hasPagesDir = existsSync(join(projectRoot, "pages"));
|
||||
const hasSrcPagesDir = existsSync(join(projectRoot, "src", "pages"));
|
||||
if (hasAppDir || hasSrcAppDir) return "app";
|
||||
if (hasPagesDir || hasSrcPagesDir) return "pages";
|
||||
return "unknown";
|
||||
};
|
||||
const detectMonorepo = (projectRoot) => {
|
||||
if (existsSync(join(projectRoot, "pnpm-workspace.yaml"))) return true;
|
||||
if (existsSync(join(projectRoot, "lerna.json"))) return true;
|
||||
const packageJsonPath = join(projectRoot, "package.json");
|
||||
if (existsSync(packageJsonPath)) try {
|
||||
if (JSON.parse(readFileSync(packageJsonPath, "utf-8")).workspaces) return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getWorkspacePatterns = (projectRoot) => {
|
||||
const patterns = [];
|
||||
const pnpmWorkspacePath = join(projectRoot, "pnpm-workspace.yaml");
|
||||
if (existsSync(pnpmWorkspacePath)) {
|
||||
const lines = readFileSync(pnpmWorkspacePath, "utf-8").split("\n");
|
||||
let inPackages = false;
|
||||
for (const line of lines) {
|
||||
if (line.match(/^packages:\s*$/)) {
|
||||
inPackages = true;
|
||||
continue;
|
||||
}
|
||||
if (inPackages) {
|
||||
if (line.match(/^[a-zA-Z]/) || line.trim() === "") {
|
||||
if (line.match(/^[a-zA-Z]/)) inPackages = false;
|
||||
continue;
|
||||
}
|
||||
const match = line.match(/^\s*-\s*['"]?([^'"#\n]+?)['"]?\s*$/);
|
||||
if (match) patterns.push(match[1].trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
const lernaJsonPath = join(projectRoot, "lerna.json");
|
||||
if (existsSync(lernaJsonPath)) try {
|
||||
const lernaJson = JSON.parse(readFileSync(lernaJsonPath, "utf-8"));
|
||||
if (Array.isArray(lernaJson.packages)) patterns.push(...lernaJson.packages);
|
||||
} catch {}
|
||||
const packageJsonPath = join(projectRoot, "package.json");
|
||||
if (existsSync(packageJsonPath)) try {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
||||
if (Array.isArray(packageJson.workspaces)) patterns.push(...packageJson.workspaces);
|
||||
else if (packageJson.workspaces?.packages) patterns.push(...packageJson.workspaces.packages);
|
||||
} catch {}
|
||||
return [...new Set(patterns)];
|
||||
};
|
||||
const expandWorkspacePattern = (projectRoot, pattern) => {
|
||||
const isGlob = pattern.endsWith("/*");
|
||||
const basePath = join(projectRoot, pattern.replace(/\/\*$/, ""));
|
||||
if (!existsSync(basePath)) return [];
|
||||
if (!isGlob) return existsSync(join(basePath, "package.json")) ? [basePath] : [];
|
||||
const results = [];
|
||||
try {
|
||||
const entries = readdirSync(basePath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
if (existsSync(join(basePath, entry.name, "package.json"))) results.push(join(basePath, entry.name));
|
||||
}
|
||||
} catch {
|
||||
return results;
|
||||
}
|
||||
return results;
|
||||
};
|
||||
const hasReactDependency = (projectPath) => {
|
||||
const dependencies = readMergedDependencies(projectPath);
|
||||
if (!dependencies) return false;
|
||||
return Boolean(dependencies["react"] || dependencies["react-dom"]);
|
||||
};
|
||||
const buildReactProject = (projectPath) => {
|
||||
const framework = detectFramework(projectPath);
|
||||
if (!hasReactDependency(projectPath) && framework === "unknown") return null;
|
||||
let name = basename(projectPath);
|
||||
const packageJsonPath = join(projectPath, "package.json");
|
||||
try {
|
||||
name = JSON.parse(readFileSync(packageJsonPath, "utf-8")).name || name;
|
||||
} catch {}
|
||||
return {
|
||||
name,
|
||||
path: projectPath,
|
||||
framework
|
||||
};
|
||||
};
|
||||
const findWorkspaceProjects = (projectRoot) => {
|
||||
const patterns = getWorkspacePatterns(projectRoot);
|
||||
const projects = [];
|
||||
for (const pattern of patterns) for (const projectPath of expandWorkspacePattern(projectRoot, pattern)) {
|
||||
const project = buildReactProject(projectPath);
|
||||
if (project) projects.push(project);
|
||||
}
|
||||
return projects;
|
||||
};
|
||||
const ALWAYS_IGNORED_DIRECTORIES = [
|
||||
"node_modules",
|
||||
".git",
|
||||
".next",
|
||||
".cache",
|
||||
".turbo",
|
||||
"dist",
|
||||
"build",
|
||||
"coverage",
|
||||
"test-results"
|
||||
];
|
||||
const loadGitignore = (projectRoot) => {
|
||||
const ignorer = ignore().add(ALWAYS_IGNORED_DIRECTORIES);
|
||||
const gitignorePath = join(projectRoot, ".gitignore");
|
||||
if (existsSync(gitignorePath)) try {
|
||||
ignorer.add(readFileSync(gitignorePath, "utf-8"));
|
||||
} catch {}
|
||||
return ignorer;
|
||||
};
|
||||
const scanDirectoryForProjects = (rootDirectory, ignorer, maxDepth, currentDepth = 0) => {
|
||||
if (currentDepth >= maxDepth) return [];
|
||||
if (!existsSync(rootDirectory)) return [];
|
||||
const projects = [];
|
||||
try {
|
||||
const entries = readdirSync(rootDirectory, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory()) continue;
|
||||
if (ignorer.ignores(entry.name)) continue;
|
||||
const entryPath = join(rootDirectory, entry.name);
|
||||
if (existsSync(join(entryPath, "package.json"))) {
|
||||
const project = buildReactProject(entryPath);
|
||||
if (project) {
|
||||
projects.push(project);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
projects.push(...scanDirectoryForProjects(entryPath, ignorer, maxDepth, currentDepth + 1));
|
||||
}
|
||||
} catch {
|
||||
return projects;
|
||||
}
|
||||
return projects;
|
||||
};
|
||||
const MAX_SCAN_DEPTH = 2;
|
||||
const normalizePathForComparison = (filePath) => filePath.replace(/\\/g, "/");
|
||||
const findReactProjects = (projectRoot) => {
|
||||
const monorepoRoot = detectMonorepo(projectRoot) ? projectRoot : findEnclosingMonorepoRoot(projectRoot);
|
||||
if (monorepoRoot) {
|
||||
const workspaceProjects = findWorkspaceProjects(monorepoRoot);
|
||||
const localProject = projectRoot === monorepoRoot ? null : buildReactProject(projectRoot);
|
||||
const projects = localProject ? [localProject, ...workspaceProjects.filter((project) => normalizePathForComparison(project.path) !== normalizePathForComparison(localProject.path))] : workspaceProjects;
|
||||
if (projects.length > 0) return projects;
|
||||
}
|
||||
const scannedProjects = scanDirectoryForProjects(projectRoot, loadGitignore(projectRoot), MAX_SCAN_DEPTH);
|
||||
if (scannedProjects.length > 0) return scannedProjects;
|
||||
let currentDirectory = dirname(projectRoot);
|
||||
while (currentDirectory !== dirname(currentDirectory)) {
|
||||
const parentProject = buildReactProject(currentDirectory);
|
||||
if (parentProject) return [parentProject];
|
||||
currentDirectory = dirname(currentDirectory);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
const hasReactGrabSetupInFile = (filePath) => {
|
||||
if (!existsSync(filePath)) return false;
|
||||
try {
|
||||
return hasReactGrabSetupCode(readFileSync(filePath, "utf-8"));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const detectReactGrabDependency = (projectRoot) => {
|
||||
const dependencies = readMergedDependencies(projectRoot);
|
||||
return Boolean(dependencies?.["react-grab"]);
|
||||
};
|
||||
const detectReactGrabConfigured = (projectRoot) => {
|
||||
return getReactGrabSetupFileCandidates(projectRoot).some(hasReactGrabSetupInFile);
|
||||
};
|
||||
const detectReactGrab = (projectRoot) => detectReactGrabDependency(projectRoot) || detectReactGrabConfigured(projectRoot);
|
||||
const detectUnsupportedFramework = (projectRoot) => {
|
||||
const dependencies = readMergedDependencies(projectRoot);
|
||||
if (!dependencies) return null;
|
||||
if (dependencies["@remix-run/react"] || dependencies["remix"]) return "remix";
|
||||
if (dependencies["astro"]) return "astro";
|
||||
if (dependencies["@sveltejs/kit"]) return "sveltekit";
|
||||
if (dependencies["gatsby"]) return "gatsby";
|
||||
return null;
|
||||
};
|
||||
const detectReactGrabVersion = (projectRoot) => {
|
||||
const installedPackageJsonPath = join(projectRoot, "node_modules", "react-grab", "package.json");
|
||||
if (existsSync(installedPackageJsonPath)) try {
|
||||
return JSON.parse(readFileSync(installedPackageJsonPath, "utf-8")).version ?? null;
|
||||
} catch {}
|
||||
return null;
|
||||
};
|
||||
const detectProject = async (projectRoot = process.cwd()) => {
|
||||
const localFramework = detectFramework(projectRoot);
|
||||
const framework = localFramework === "unknown" ? detectFrameworkFromMonorepoRoot(projectRoot) : localFramework;
|
||||
const packageManager = await detectPackageManager(projectRoot);
|
||||
const isMonorepo = detectMonorepo(projectRoot) || findEnclosingMonorepoRoot(projectRoot) !== null;
|
||||
const isReactGrabConfigured = detectReactGrabConfigured(projectRoot);
|
||||
return {
|
||||
packageManager,
|
||||
framework,
|
||||
nextRouterType: framework === "next" ? detectNextRouterType(projectRoot) : "unknown",
|
||||
isMonorepo,
|
||||
projectRoot,
|
||||
hasReactGrab: detectReactGrabDependency(projectRoot) || isReactGrabConfigured,
|
||||
isReactGrabConfigured,
|
||||
reactGrabVersion: detectReactGrabVersion(projectRoot),
|
||||
unsupportedFramework: detectUnsupportedFramework(projectRoot)
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
//#region src/utils/detect-agents.ts
|
||||
const PATH_BINARIES = {
|
||||
"claude-code": ["claude"],
|
||||
codex: ["codex"],
|
||||
cursor: ["cursor", "cursor-agent"],
|
||||
droid: ["droid"],
|
||||
"gemini-cli": ["gemini"],
|
||||
"github-copilot": ["copilot"],
|
||||
opencode: ["opencode"],
|
||||
pi: ["pi", "omegon"]
|
||||
};
|
||||
const isCommandAvailable = (command) => {
|
||||
const pathDirectories = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
||||
for (const directory of pathDirectories) {
|
||||
const binaryPath = join(directory, command);
|
||||
try {
|
||||
if (statSync(binaryPath).isFile()) {
|
||||
accessSync(binaryPath, constants.X_OK);
|
||||
return true;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const detectAvailableAgents = async () => {
|
||||
const installedAgents = new Set(await detectInstalledSkillAgents());
|
||||
return getSkillAgentTypes().filter((agent) => {
|
||||
if (agent === "universal") return false;
|
||||
if (installedAgents.has(agent)) return true;
|
||||
return PATH_BINARIES[agent]?.some(isCommandAvailable) ?? false;
|
||||
});
|
||||
};
|
||||
//#endregion
|
||||
//#region src/utils/install-skill.ts
|
||||
const SKILL_NAME = "react-grab";
|
||||
const SKILL_SOURCE = fileURLToPath(new URL("../skills/react-grab", import.meta.url));
|
||||
const agentLabel = (agent) => getSkillAgentConfig(agent).displayName;
|
||||
const installedSkillDir = (agent, global, cwd) => join(isUniversalSkillAgent(agent) ? getCanonicalSkillsDir(global, cwd) : getSkillAgentDir(agent, {
|
||||
global,
|
||||
cwd
|
||||
}), SKILL_NAME);
|
||||
const installSkill = async ({ agents, global = false, cwd = process.cwd() } = {}) => {
|
||||
return add({
|
||||
source: SKILL_SOURCE,
|
||||
agents: agents ?? await detectAvailableAgents(),
|
||||
global,
|
||||
cwd,
|
||||
mode: "copy"
|
||||
});
|
||||
};
|
||||
const removeSkill = async ({ cwd = process.cwd(), global = false } = {}) => {
|
||||
const agents = await detectAvailableAgents();
|
||||
const removedAgents = [];
|
||||
const dirsToRemove = /* @__PURE__ */ new Set();
|
||||
for (const agent of agents) {
|
||||
const skillDir = installedSkillDir(agent, global, cwd);
|
||||
if (!existsSync(skillDir)) continue;
|
||||
removedAgents.push(agent);
|
||||
dirsToRemove.add(skillDir);
|
||||
}
|
||||
for (const skillDir of dirsToRemove) rmSync(skillDir, {
|
||||
recursive: true,
|
||||
force: true
|
||||
});
|
||||
return removedAgents;
|
||||
};
|
||||
//#endregion
|
||||
//#region src/utils/templates.ts
|
||||
const NEXT_APP_ROUTER_SCRIPT = `{process.env.NODE_ENV === "development" && (
|
||||
<Script
|
||||
src="//unpkg.com/react-grab/dist/index.global.js"
|
||||
crossOrigin="anonymous"
|
||||
strategy="beforeInteractive"
|
||||
/>
|
||||
)}`;
|
||||
const VITE_IMPORT = `if (import.meta.env.DEV) {
|
||||
import("react-grab");
|
||||
}`;
|
||||
const WEBPACK_IMPORT = `if (process.env.NODE_ENV === "development") {
|
||||
import("react-grab");
|
||||
}`;
|
||||
const TANSTACK_EFFECT = `useEffect(() => {
|
||||
if (import.meta.env.DEV) {
|
||||
void import("react-grab");
|
||||
}
|
||||
}, []);`;
|
||||
const SCRIPT_IMPORT = "import Script from \"next/script\";";
|
||||
//#endregion
|
||||
//#region src/utils/transform.ts
|
||||
const hasReactGrabInInstrumentation = (projectRoot) => {
|
||||
return findFileWithReactGrabSetup(getInstrumentationFileCandidates(projectRoot)) !== null;
|
||||
};
|
||||
const findFileWithReactGrabSetup = (fileCandidates) => {
|
||||
for (const filePath of fileCandidates) {
|
||||
if (!existsSync(filePath)) continue;
|
||||
if (hasReactGrabSetupCode(readFileSync(filePath, "utf-8"))) return filePath;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const alreadyConfiguredResult = (filePath) => ({
|
||||
success: true,
|
||||
filePath,
|
||||
message: "React Grab is already configured",
|
||||
noChanges: true
|
||||
});
|
||||
const transformNextAppRouter = (projectRoot, reactGrabAlreadyConfigured) => {
|
||||
const layoutPath = findLayoutFile(projectRoot);
|
||||
if (!layoutPath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find app/layout.tsx, app/layout.jsx, app/layout.ts, or app/layout.js"
|
||||
};
|
||||
const originalContent = readFileSync(layoutPath, "utf-8");
|
||||
let newContent = originalContent;
|
||||
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
||||
const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
|
||||
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(layoutPath);
|
||||
if (hasReactGrabInFile || hasReactGrabInInstrumentationFile) return {
|
||||
success: true,
|
||||
filePath: layoutPath,
|
||||
message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
|
||||
noChanges: true
|
||||
};
|
||||
if (!newContent.includes("import Script from \"next/script\"")) {
|
||||
const importMatch = newContent.match(/^import .+ from ['"].+['"];?\s*$/m);
|
||||
if (importMatch) newContent = newContent.replace(importMatch[0], `${importMatch[0]}\n${SCRIPT_IMPORT}`);
|
||||
else newContent = `${SCRIPT_IMPORT}\n\n${newContent}`;
|
||||
}
|
||||
const headMatch = newContent.match(/<head[^>]*>/);
|
||||
if (headMatch) newContent = newContent.replace(headMatch[0], `${headMatch[0]}\n ${NEXT_APP_ROUTER_SCRIPT}`);
|
||||
else {
|
||||
const htmlMatch = newContent.match(/<html[^>]*>/);
|
||||
if (htmlMatch) newContent = newContent.replace(htmlMatch[0], `${htmlMatch[0]}\n <head>\n ${NEXT_APP_ROUTER_SCRIPT}\n </head>`);
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
filePath: layoutPath,
|
||||
message: "Add React Grab",
|
||||
originalContent,
|
||||
newContent
|
||||
};
|
||||
};
|
||||
const transformNextPagesRouter = (projectRoot, reactGrabAlreadyConfigured) => {
|
||||
const documentPath = findDocumentFile(projectRoot);
|
||||
if (!documentPath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
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 }"
|
||||
};
|
||||
const originalContent = readFileSync(documentPath, "utf-8");
|
||||
let newContent = originalContent;
|
||||
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
||||
const hasReactGrabInInstrumentationFile = hasReactGrabInInstrumentation(projectRoot);
|
||||
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(documentPath);
|
||||
if (hasReactGrabInFile || hasReactGrabInInstrumentationFile) return {
|
||||
success: true,
|
||||
filePath: documentPath,
|
||||
message: "React Grab is already installed" + (hasReactGrabInInstrumentationFile ? " in instrumentation-client" : " in this file"),
|
||||
noChanges: true
|
||||
};
|
||||
if (!newContent.includes("import Script from \"next/script\"")) {
|
||||
const importMatch = newContent.match(/^import .+ from ['"].+['"];?\s*$/m);
|
||||
if (importMatch) newContent = newContent.replace(importMatch[0], `${importMatch[0]}\n${SCRIPT_IMPORT}`);
|
||||
}
|
||||
const headMatch = newContent.match(/<Head[^>]*>/);
|
||||
if (headMatch) newContent = newContent.replace(headMatch[0], `${headMatch[0]}\n ${NEXT_APP_ROUTER_SCRIPT}`);
|
||||
return {
|
||||
success: true,
|
||||
filePath: documentPath,
|
||||
message: "Add React Grab",
|
||||
originalContent,
|
||||
newContent
|
||||
};
|
||||
};
|
||||
const checkExistingInstallation = (filePath, reactGrabAlreadyConfigured) => {
|
||||
if (!hasReactGrabSetupCode(readFileSync(filePath, "utf-8"))) return null;
|
||||
return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: reactGrabAlreadyConfigured ? "React Grab is already configured" : "React Grab is already installed in this file",
|
||||
noChanges: true
|
||||
};
|
||||
};
|
||||
const transformVite = (projectRoot, reactGrabAlreadyConfigured) => {
|
||||
const entryPath = findEntryFile(projectRoot);
|
||||
const indexPath = findIndexHtml(projectRoot);
|
||||
if (indexPath) {
|
||||
const existingResult = checkExistingInstallation(indexPath, reactGrabAlreadyConfigured);
|
||||
if (existingResult) return existingResult;
|
||||
}
|
||||
if (!entryPath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find entry file (src/index.tsx, src/main.tsx, etc.)"
|
||||
};
|
||||
const existingResult = checkExistingInstallation(entryPath, reactGrabAlreadyConfigured);
|
||||
if (existingResult) return existingResult;
|
||||
const originalContent = readFileSync(entryPath, "utf-8");
|
||||
return {
|
||||
success: true,
|
||||
filePath: entryPath,
|
||||
message: "Add React Grab",
|
||||
originalContent,
|
||||
newContent: `${VITE_IMPORT}\n\n${originalContent}`
|
||||
};
|
||||
};
|
||||
const transformWebpack = (projectRoot, reactGrabAlreadyConfigured) => {
|
||||
const entryPath = findEntryFile(projectRoot);
|
||||
if (!entryPath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find entry file (src/index.tsx, src/main.tsx, etc.)"
|
||||
};
|
||||
const existingResult = checkExistingInstallation(entryPath, reactGrabAlreadyConfigured);
|
||||
if (existingResult) return existingResult;
|
||||
const originalContent = readFileSync(entryPath, "utf-8");
|
||||
return {
|
||||
success: true,
|
||||
filePath: entryPath,
|
||||
message: "Add React Grab",
|
||||
originalContent,
|
||||
newContent: `${WEBPACK_IMPORT}\n\n${originalContent}`
|
||||
};
|
||||
};
|
||||
const transformTanStack = (projectRoot, reactGrabAlreadyConfigured) => {
|
||||
const rootPath = findTanStackRootFile(projectRoot);
|
||||
if (!rootPath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find src/routes/__root.tsx or app/routes/__root.tsx.\n\nTo set up React Grab with TanStack Start, add this to your root route component:\n\n import { useEffect } from \"react\";\n\n useEffect(() => {\n if (import.meta.env.DEV) {\n void import(\"react-grab\");\n }\n }, []);"
|
||||
};
|
||||
const originalContent = readFileSync(rootPath, "utf-8");
|
||||
let newContent = originalContent;
|
||||
const hasReactGrabInFile = hasReactGrabSetupCode(originalContent);
|
||||
if (hasReactGrabInFile && reactGrabAlreadyConfigured) return alreadyConfiguredResult(rootPath);
|
||||
if (hasReactGrabInFile) return {
|
||||
success: true,
|
||||
filePath: rootPath,
|
||||
message: "React Grab is already installed in this file",
|
||||
noChanges: true
|
||||
};
|
||||
if (!/import\s+\{[^}]*useEffect[^}]*\}\s+from\s+["']react["']/.test(newContent)) {
|
||||
const reactImportMatch = newContent.match(/import\s+\{([^}]*)\}\s+from\s+["']react["'];?/);
|
||||
if (reactImportMatch) {
|
||||
const existingImports = reactImportMatch[1];
|
||||
newContent = newContent.replace(reactImportMatch[0], `import { ${existingImports.trim()}, useEffect } from "react";`);
|
||||
} else {
|
||||
const firstImportMatch = newContent.match(/^import .+ from ['"].+['"];?\s*$/m);
|
||||
if (firstImportMatch) newContent = newContent.replace(firstImportMatch[0], `import { useEffect } from "react";\n${firstImportMatch[0]}`);
|
||||
else newContent = `import { useEffect } from "react";\n\n${newContent}`;
|
||||
}
|
||||
}
|
||||
const componentMatch = newContent.match(/function\s+(\w+)\s*\([^)]*\)\s*\{/);
|
||||
if (componentMatch) {
|
||||
const insertPosition = componentMatch.index + componentMatch[0].length;
|
||||
newContent = newContent.slice(0, insertPosition) + `\n ${TANSTACK_EFFECT}\n` + newContent.slice(insertPosition);
|
||||
} else return {
|
||||
success: false,
|
||||
filePath: rootPath,
|
||||
message: "Could not find a component function in the root file"
|
||||
};
|
||||
return {
|
||||
success: true,
|
||||
filePath: rootPath,
|
||||
message: "Add React Grab",
|
||||
originalContent,
|
||||
newContent
|
||||
};
|
||||
};
|
||||
const hasFrameworkEntryPoint = (projectRoot, framework, nextRouterType) => {
|
||||
switch (framework) {
|
||||
case "next": return nextRouterType === "app" ? findLayoutFile(projectRoot) !== null : findDocumentFile(projectRoot) !== null;
|
||||
case "vite":
|
||||
case "webpack": return findEntryFile(projectRoot) !== null;
|
||||
case "tanstack": return findTanStackRootFile(projectRoot) !== null;
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
const previewTransform = (projectRoot, framework, nextRouterType, reactGrabAlreadyConfigured = false) => {
|
||||
switch (framework) {
|
||||
case "next":
|
||||
if (nextRouterType === "app") return transformNextAppRouter(projectRoot, reactGrabAlreadyConfigured);
|
||||
return transformNextPagesRouter(projectRoot, reactGrabAlreadyConfigured);
|
||||
case "vite": return transformVite(projectRoot, reactGrabAlreadyConfigured);
|
||||
case "tanstack": return transformTanStack(projectRoot, reactGrabAlreadyConfigured);
|
||||
case "webpack": return transformWebpack(projectRoot, reactGrabAlreadyConfigured);
|
||||
default: return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: `Unknown framework: ${framework}. Please add React Grab manually.`
|
||||
};
|
||||
}
|
||||
};
|
||||
const canWriteToFile = (filePath) => {
|
||||
try {
|
||||
accessSync(filePath, constants.W_OK);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const applyTransform = (result) => {
|
||||
if (result.success && result.newContent && result.filePath) {
|
||||
if (!canWriteToFile(result.filePath)) return {
|
||||
success: false,
|
||||
error: `Cannot write to ${result.filePath}. Check file permissions.`
|
||||
};
|
||||
try {
|
||||
writeFileSync(result.filePath, result.newContent);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: `Failed to write to ${result.filePath}: ${error instanceof Error ? error.message : "Unknown error"}`
|
||||
};
|
||||
}
|
||||
}
|
||||
return { success: true };
|
||||
};
|
||||
const formatOptionsForNextjs = (options) => {
|
||||
const parts = [];
|
||||
if (options.activationKey) parts.push(`activationKey: ${JSON.stringify(options.activationKey)}`);
|
||||
if (options.activationMode) parts.push(`activationMode: "${options.activationMode}"`);
|
||||
if (options.keyHoldDuration !== void 0) parts.push(`keyHoldDuration: ${options.keyHoldDuration}`);
|
||||
if (options.allowActivationInsideInput !== void 0) parts.push(`allowActivationInsideInput: ${options.allowActivationInsideInput}`);
|
||||
if (options.maxContextLines !== void 0) parts.push(`maxContextLines: ${options.maxContextLines}`);
|
||||
return `{ ${parts.join(", ")} }`;
|
||||
};
|
||||
const formatOptionsAsJson = (options) => {
|
||||
const cleanOptions = {};
|
||||
if (options.activationKey) cleanOptions.activationKey = options.activationKey;
|
||||
if (options.activationMode) cleanOptions.activationMode = options.activationMode;
|
||||
if (options.keyHoldDuration !== void 0) cleanOptions.keyHoldDuration = options.keyHoldDuration;
|
||||
if (options.allowActivationInsideInput !== void 0) cleanOptions.allowActivationInsideInput = options.allowActivationInsideInput;
|
||||
if (options.maxContextLines !== void 0) cleanOptions.maxContextLines = options.maxContextLines;
|
||||
return JSON.stringify(cleanOptions);
|
||||
};
|
||||
const findReactGrabFile = (projectRoot, framework, nextRouterType) => {
|
||||
switch (framework) {
|
||||
case "next": {
|
||||
const primaryFile = nextRouterType === "app" ? findLayoutFile(projectRoot) : findDocumentFile(projectRoot);
|
||||
const primarySetupFile = findFileWithReactGrabSetup(nextRouterType === "app" ? getLayoutFileCandidates(projectRoot) : getDocumentFileCandidates(projectRoot));
|
||||
if (primarySetupFile) return primarySetupFile;
|
||||
const instrumentationFile = findFileWithReactGrabSetup(getInstrumentationFileCandidates(projectRoot));
|
||||
if (instrumentationFile) return instrumentationFile;
|
||||
return primaryFile;
|
||||
}
|
||||
case "vite": {
|
||||
const entryFile = findEntryFile(projectRoot);
|
||||
const entrySetupFile = findFileWithReactGrabSetup(getEntryFileCandidates(projectRoot));
|
||||
if (entrySetupFile) return entrySetupFile;
|
||||
const indexHtml = findFileWithReactGrabSetup(getIndexHtmlCandidates(projectRoot));
|
||||
if (indexHtml) return indexHtml;
|
||||
return entryFile;
|
||||
}
|
||||
case "tanstack": return findFileWithReactGrabSetup(getTanStackRootFileCandidates(projectRoot)) ?? findTanStackRootFile(projectRoot);
|
||||
case "webpack": return findFileWithReactGrabSetup(getEntryFileCandidates(projectRoot)) ?? findEntryFile(projectRoot);
|
||||
default: return null;
|
||||
}
|
||||
};
|
||||
const addOptionsToNextScript = (originalContent, options, filePath) => {
|
||||
const reactGrabScriptMatch = originalContent.match(/(<Script[\s\S]*?react-grab[\s\S]*?)\s*(\/?>)/i);
|
||||
if (!reactGrabScriptMatch) return {
|
||||
success: false,
|
||||
filePath,
|
||||
message: "Could not find React Grab Script tag"
|
||||
};
|
||||
const scriptTag = reactGrabScriptMatch[0];
|
||||
const scriptOpening = reactGrabScriptMatch[1];
|
||||
const scriptClosing = reactGrabScriptMatch[2];
|
||||
const existingDataOptionsMatch = scriptTag.match(/data-options=\{JSON\.stringify\([^)]+\)\}/);
|
||||
const dataOptionsAttr = `data-options={JSON.stringify(\n ${formatOptionsForNextjs(options)}\n )}`;
|
||||
let newScriptTag;
|
||||
if (existingDataOptionsMatch) newScriptTag = scriptTag.replace(existingDataOptionsMatch[0], dataOptionsAttr);
|
||||
else newScriptTag = `${scriptOpening}\n ${dataOptionsAttr}\n ${scriptClosing}`;
|
||||
return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: "Update React Grab options",
|
||||
originalContent,
|
||||
newContent: originalContent.replace(scriptTag, newScriptTag)
|
||||
};
|
||||
};
|
||||
const addOptionsToDynamicImport = (originalContent, options, filePath) => {
|
||||
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*\))?/);
|
||||
if (!reactGrabImportWithInitMatch) return {
|
||||
success: false,
|
||||
filePath,
|
||||
message: "Could not find React Grab import"
|
||||
};
|
||||
const optionsJson = formatOptionsAsJson(options);
|
||||
const newImport = `${reactGrabImportWithInitMatch[1] ?? ""}import("react-grab").then((m) => m.init(${optionsJson}))`;
|
||||
return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: "Update React Grab options",
|
||||
originalContent,
|
||||
newContent: originalContent.replace(reactGrabImportWithInitMatch[0], newImport)
|
||||
};
|
||||
};
|
||||
const addOptionsToTanStackImport = (originalContent, options, filePath) => {
|
||||
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*\))/);
|
||||
if (!reactGrabImportWithInitMatch) return {
|
||||
success: false,
|
||||
filePath,
|
||||
message: "Could not find React Grab import"
|
||||
};
|
||||
const optionsJson = formatOptionsAsJson(options);
|
||||
const newImport = `${reactGrabImportWithInitMatch[1] ?? reactGrabImportWithInitMatch[2] ?? ""}import("react-grab/core").then(({ init }) => init(${optionsJson}))`;
|
||||
return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: "Update React Grab options",
|
||||
originalContent,
|
||||
newContent: originalContent.replace(reactGrabImportWithInitMatch[0], newImport)
|
||||
};
|
||||
};
|
||||
const addOptionsToAnyImport = (originalContent, options, filePath) => {
|
||||
const dynamicImportResult = addOptionsToDynamicImport(originalContent, options, filePath);
|
||||
if (dynamicImportResult.success) return dynamicImportResult;
|
||||
return addOptionsToTanStackImport(originalContent, options, filePath);
|
||||
};
|
||||
const previewOptionsTransform = (projectRoot, framework, nextRouterType, options) => {
|
||||
const filePath = findReactGrabFile(projectRoot, framework, nextRouterType);
|
||||
if (!filePath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find file containing React Grab configuration"
|
||||
};
|
||||
const originalContent = readFileSync(filePath, "utf-8");
|
||||
if (!hasReactGrabSetupCode(originalContent)) return {
|
||||
success: false,
|
||||
filePath,
|
||||
message: "Could not find React Grab code in the file"
|
||||
};
|
||||
switch (framework) {
|
||||
case "next":
|
||||
if (isInstrumentationFile(filePath)) return addOptionsToAnyImport(originalContent, options, filePath);
|
||||
return addOptionsToNextScript(originalContent, options, filePath);
|
||||
case "vite": return addOptionsToDynamicImport(originalContent, options, filePath);
|
||||
case "tanstack": return addOptionsToTanStackImport(originalContent, options, filePath);
|
||||
case "webpack": return addOptionsToDynamicImport(originalContent, options, filePath);
|
||||
default: return {
|
||||
success: false,
|
||||
filePath,
|
||||
message: `Unknown framework: ${framework}`
|
||||
};
|
||||
}
|
||||
};
|
||||
const previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDomain) => {
|
||||
const filePath = findReactGrabFile(projectRoot, framework, nextRouterType);
|
||||
if (!filePath) return {
|
||||
success: false,
|
||||
filePath: "",
|
||||
message: "Could not find React Grab file"
|
||||
};
|
||||
const originalContent = readFileSync(filePath, "utf-8");
|
||||
const newContent = originalContent.replace(/(https?:)?\/\/[^/\s"']+(?=\/(?:@?react-grab))/g, `//${targetCdnDomain}`).replace(/(https?:)?\/\/[^/\s"']*react-grab[^/\s"']*\.com(?=\/script\.js)/g, `//${targetCdnDomain}`);
|
||||
if (newContent === originalContent) return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: "CDN already set",
|
||||
noChanges: true
|
||||
};
|
||||
return {
|
||||
success: true,
|
||||
filePath,
|
||||
message: "Update CDN",
|
||||
originalContent,
|
||||
newContent
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
//#region src/utils/install.ts
|
||||
const installPackages = async (packages, options = {}) => {
|
||||
if (packages.length === 0) return;
|
||||
const detectedAgent = options.packageManager ?? await detectPackageManager(options.cwd ?? process.cwd());
|
||||
const args = [];
|
||||
if (options.preferOffline) args.push("--prefer-offline");
|
||||
if (detectedAgent === "pnpm") {
|
||||
args.push("--prod=false");
|
||||
if (existsSync(resolve(options.cwd ?? process.cwd(), "pnpm-workspace.yaml"))) args.push("-w");
|
||||
}
|
||||
if (options.additionalArgs) args.push(...options.additionalArgs);
|
||||
await x(detectedAgent, [
|
||||
detectedAgent === "npm" ? "install" : "add",
|
||||
...options.isDev !== false ? ["-D"] : [],
|
||||
...args,
|
||||
...packages
|
||||
], {
|
||||
nodeOptions: {
|
||||
stdio: options.silent ? "ignore" : "inherit",
|
||||
cwd: options.cwd,
|
||||
env: {
|
||||
...process.env,
|
||||
REACT_GRAB_INIT: "1"
|
||||
}
|
||||
},
|
||||
throwOnError: true
|
||||
});
|
||||
};
|
||||
const getPackagesToInstall = (includeReactGrab = true) => {
|
||||
return includeReactGrab ? ["react-grab"] : [];
|
||||
};
|
||||
//#endregion
|
||||
export { detectReactGrabConfigured as _, previewCdnTransform as a, agentLabel as c, detectAvailableAgents as d, detectFramework as f, detectReactGrab as g, detectProject as h, hasFrameworkEntryPoint as i, installSkill as l, detectPackageManager as m, installPackages as n, previewOptionsTransform as o, detectNextRouterType as p, applyTransform as r, previewTransform as s, getPackagesToInstall as t, removeSkill as u, detectUnsupportedFramework as v, findReactProjects as y };
|
||||
|
||||
//# sourceMappingURL=install-Car5vKPk.js.map
|
||||
1
node_modules/@react-grab/cli/dist/install-Car5vKPk.js.map
generated
vendored
Normal file
1
node_modules/@react-grab/cli/dist/install-Car5vKPk.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1004
node_modules/@react-grab/cli/dist/install-DlD3sLtm.cjs
generated
vendored
Normal file
1004
node_modules/@react-grab/cli/dist/install-DlD3sLtm.cjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
111
node_modules/@react-grab/cli/dist/read-clipboard.ps1
generated
vendored
Normal file
111
node_modules/@react-grab/cli/dist/read-clipboard.ps1
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
# Windows clipboard reader for `react-grab watch`. Reads CF_UNICODETEXT and the
|
||||
# registered "Chromium Web Custom MIME Data Format" (a base::Pickle of web custom
|
||||
# data) via Win32, in a single OpenClipboard so the two reads are consistent.
|
||||
# Emits { changeCount, text, pickleBase64 } as JSON; the CLI decodes the pickle
|
||||
# (shared with macOS/Linux). GetClipboardSequenceNumber gives a cheap monotonic
|
||||
# change token for idle polling.
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$source = @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public static class RgClip {
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool CloseClipboard();
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetClipboardData(uint uFormat);
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern uint RegisterClipboardFormat(string lpszFormat);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern uint GetClipboardSequenceNumber();
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool IsClipboardFormatAvailable(uint format);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GlobalLock(IntPtr hMem);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GlobalUnlock(IntPtr hMem);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern UIntPtr GlobalSize(IntPtr hMem);
|
||||
|
||||
private const uint CF_UNICODETEXT = 13;
|
||||
|
||||
private static byte[] ReadLocked(uint format) {
|
||||
if (!IsClipboardFormatAvailable(format)) return null;
|
||||
IntPtr handle = GetClipboardData(format);
|
||||
if (handle == IntPtr.Zero) return null;
|
||||
IntPtr pointer = GlobalLock(handle);
|
||||
if (pointer == IntPtr.Zero) return null;
|
||||
try {
|
||||
ulong size = GlobalSize(handle).ToUInt64();
|
||||
if (size == 0 || size > int.MaxValue) return null;
|
||||
byte[] bytes = new byte[(int)size];
|
||||
Marshal.Copy(pointer, bytes, 0, (int)size);
|
||||
return bytes;
|
||||
} finally {
|
||||
GlobalUnlock(handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[][] ReadAll(uint customFormat) {
|
||||
byte[][] result = new byte[2][];
|
||||
if (!OpenClipboard(IntPtr.Zero)) return result;
|
||||
try {
|
||||
result[0] = ReadLocked(CF_UNICODETEXT);
|
||||
result[1] = ReadLocked(customFormat);
|
||||
} finally {
|
||||
CloseClipboard();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
# Add-Type recompiles on every process start, so the reader is compiled to a
|
||||
# cached assembly once and merely loaded on subsequent polls.
|
||||
$cacheDir = Join-Path $env:TEMP "react-grab-watch"
|
||||
# Key the cached DLL by a hash of the source so a changed reader recompiles
|
||||
# instead of loading a stale assembly.
|
||||
$sourceHashBytes = [System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($source))
|
||||
$sourceHash = ([System.BitConverter]::ToString($sourceHashBytes) -replace "-", "").Substring(0, 16)
|
||||
$cachedDll = Join-Path $cacheDir "RgClipReader-$sourceHash.dll"
|
||||
$loaded = $false
|
||||
if (Test-Path $cachedDll) {
|
||||
try { Add-Type -Path $cachedDll | Out-Null; $loaded = $true } catch {}
|
||||
}
|
||||
if (-not $loaded) {
|
||||
try {
|
||||
New-Item -ItemType Directory -Force -Path $cacheDir | Out-Null
|
||||
Add-Type -TypeDefinition $source -Language CSharp -OutputAssembly $cachedDll -ErrorAction Stop | Out-Null
|
||||
Add-Type -Path $cachedDll | Out-Null
|
||||
$loaded = $true
|
||||
} catch {}
|
||||
}
|
||||
if (-not $loaded) {
|
||||
Add-Type -TypeDefinition $source -Language CSharp | Out-Null
|
||||
}
|
||||
|
||||
$changeCount = [RgClip]::GetClipboardSequenceNumber()
|
||||
$customFormat = [RgClip]::RegisterClipboardFormat("Chromium Web Custom MIME Data Format")
|
||||
$blobs = [RgClip]::ReadAll($customFormat)
|
||||
|
||||
$text = $null
|
||||
if ($null -ne $blobs[0]) {
|
||||
$text = [System.Text.Encoding]::Unicode.GetString($blobs[0]).TrimEnd([char]0)
|
||||
}
|
||||
|
||||
$pickleBase64 = $null
|
||||
if ($null -ne $blobs[1]) {
|
||||
$pickleBase64 = [System.Convert]::ToBase64String($blobs[1])
|
||||
}
|
||||
|
||||
$payload = [ordered]@{
|
||||
changeCount = [int64]$changeCount
|
||||
text = $text
|
||||
pickleBase64 = $pickleBase64
|
||||
}
|
||||
|
||||
$payload | ConvertTo-Json -Compress
|
||||
35
node_modules/@react-grab/cli/dist/read-clipboard.swift
generated
vendored
Normal file
35
node_modules/@react-grab/cli/dist/read-clipboard.swift
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import AppKit
|
||||
|
||||
// macOS clipboard reader for `react-grab watch`. React Grab's custom MIME type
|
||||
// is not exposed directly by Chromium-based browsers: the legacy
|
||||
// execCommand("copy") + dataTransfer.setData path lands as a base::Pickle under
|
||||
// "org.chromium.web-custom-data"; the async Clipboard API path lands as raw
|
||||
// bytes referenced by "org.w3.web-custom-format.map". This reader emits the
|
||||
// pickle as base64 (the CLI decodes it, shared with Linux/Windows) and the W3C
|
||||
// payload as a resolved string, plus changeCount for cheap idle polling.
|
||||
|
||||
let GRAB_MIME = "application/x-react-grab"
|
||||
let pasteboard = NSPasteboard.general
|
||||
var result: [String: Any] = ["changeCount": pasteboard.changeCount]
|
||||
|
||||
if let text = pasteboard.string(forType: .string) {
|
||||
result["text"] = text
|
||||
}
|
||||
|
||||
if let data = pasteboard.data(forType: NSPasteboard.PasteboardType("org.chromium.web-custom-data")) {
|
||||
result["pickleBase64"] = data.base64EncodedString()
|
||||
}
|
||||
|
||||
if let mapData = pasteboard.data(
|
||||
forType: NSPasteboard.PasteboardType("org.w3.web-custom-format.map")),
|
||||
let mapString = String(data: mapData, encoding: .utf8),
|
||||
let mapJson = try? JSONSerialization.jsonObject(with: Data(mapString.utf8)) as? [String: String],
|
||||
let pasteboardType = mapJson["web " + GRAB_MIME] ?? mapJson[GRAB_MIME],
|
||||
let raw = pasteboard.data(forType: NSPasteboard.PasteboardType(pasteboardType)),
|
||||
let value = String(data: raw, encoding: .utf8)
|
||||
{
|
||||
result["grab"] = value
|
||||
}
|
||||
|
||||
let outData = (try? JSONSerialization.data(withJSONObject: result, options: [])) ?? Data("{}".utf8)
|
||||
FileHandle.standardOutput.write(outData)
|
||||
Reference in New Issue
Block a user