viewgate-wrapper 1.11.27 → 1.11.29

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 CHANGED
@@ -11,15 +11,26 @@ npm install viewgate-wrapper
11
11
 
12
12
  ---
13
13
 
14
- ## 🚀 Precision Mapping (New)
14
+ ## 🚀 Quick Setup (Automatic)
15
15
 
16
- ViewGate features a **Hybrid Precision Strategy** to ensure AI-driven code changes are 100% accurate.
16
+ The easiest way to configure ViewGate for **High-Precision Mapping** and **AI Automation** is using our CLI tool:
17
17
 
18
- ### ⚡ Vite (Recommended)
19
- Add it to `vite.config.ts`. Injects stable `data-vg-id` attributes.
18
+ ```bash
19
+ npx viewgate-wrapper setup
20
+ ```
21
+ This command automatically detects your framework (Next.js, Vite, Webpack, etc.) and injects the necessary plugins/loaders into your configuration files.
22
+
23
+ ---
24
+
25
+ ## 🛠️ Manual Configuration
26
+
27
+ If the automatic setup doesn't fit your needs, you can configure the build-time plugins manually to achieve **Surgical Precision**.
28
+
29
+ ### ⚡ Vite (Vite, Remix, Astro)
30
+ Add the plugin to your `vite.config.ts`. Works with React, Remix, and Astro.
20
31
 
21
32
  ```typescript
22
- import { viewgatePlugin } from 'viewgate-wrapper';
33
+ import { viewgatePlugin } from 'viewgate-wrapper/vite';
23
34
 
24
35
  export default defineConfig({
25
36
  plugins: [
@@ -29,40 +40,63 @@ export default defineConfig({
29
40
  });
30
41
  ```
31
42
 
32
- ### 📦 Webpack (Next.js, CRA, Custom)
33
- Add the loader to your `webpack.config.js` or `next.config.js`:
43
+ ### 📦 Next.js
44
+ Add the loader to your `next.config.js` or `next.config.mjs`:
34
45
 
35
46
  ```javascript
36
- // next.config.js or webpack.config.js
37
- module.exports = {
47
+ /** @type {import('next').NextConfig} */
48
+ const nextConfig = {
38
49
  webpack: (config) => {
39
50
  config.module.rules.push({
40
- test: /\.(tsx|jsx)$/,
51
+ test: /\.(js|jsx|ts|tsx)$/,
41
52
  exclude: /node_modules/,
42
- use: [{ loader: 'viewgate-wrapper/dist/plugin/webpack-loader' }],
53
+ use: ['viewgate-wrapper/next-loader'],
43
54
  });
44
55
  return config;
45
56
  },
46
57
  };
58
+
59
+ module.exports = nextConfig;
60
+ ```
61
+
62
+ ### 📦 Webpack (CRA Ejected, Craco, Custom)
63
+ Add the loader to your `webpack.config.js`:
64
+
65
+ ```javascript
66
+ module.exports = {
67
+ module: {
68
+ rules: [
69
+ {
70
+ test: /\.(tsx|jsx|ts|js)$/,
71
+ exclude: /node_modules/,
72
+ use: [{ loader: 'viewgate-wrapper/webpack-loader' }],
73
+ },
74
+ ],
75
+ },
76
+ };
47
77
  ```
48
78
 
49
- ### 🍄 Babel (Universal)
50
- If you are using a custom Babel setup (e.g., with `@babel/preset-react`), add the plugin to your `.babelrc` or `babel.config.js`:
79
+ ### 🍄 Babel (Universal Fallback)
80
+ Add the plugin to your `.babelrc`, `babel.config.js`, or the `babel` key in `package.json`:
51
81
 
52
82
  ```json
53
83
  {
54
- "plugins": ["viewgate-wrapper/dist/plugin/babel-plugin-viewgate"]
84
+ "plugins": ["viewgate-wrapper/babel"]
55
85
  }
56
86
  ```
57
87
 
58
- ### ⚛️ Zero-Config React (Fiber Fallback)
59
- If you can't use a build-time plugin, ViewGate automatically uses **React Fiber Detection** in development.
60
- - **Precision**: High (Line/Column level).
61
- - **Setup**: None. Works out of the box by inspecting the React tree.
62
- - **Heuristics**: Uses **Semantic Fingerprinting** (Tag + ARIA + Roles + Hierarchy) as a safety net.
88
+ ---
89
+
90
+ ## ⚛️ Zero-Config React (Fiber Fallback)
91
+
92
+ If you can't use a build-time plugin (e.g., non-ejected Create React App), ViewGate automatically uses **React Fiber Detection** in development.
93
+
94
+ - **Precision**: High (inspects the live React tree).
95
+ - **Setup**: **None**. Works out of the box.
96
+ - **Heuristics**: Uses **Semantic Fingerprinting** as a safety net.
63
97
 
64
98
  > [!IMPORTANT]
65
- > To achieve "Surgical Precision", we recommend using a build-time plugin (Vite, Webpack, or Babel) whenever possible.
99
+ > For the best experience with AI automation (Surgical Precision), we recommend using one of the build-time plugins mentioned above.
66
100
 
67
101
  ---
68
102
 
@@ -100,15 +134,8 @@ function Root() {
100
134
 
101
135
  ViewGate includes a **Model Context Protocol (MCP)** server that allows AI assistants (like Claude Desktop, Cursor, or Antigravity) to read your UI feedback and apply requested code changes automatically.
102
136
 
103
- ### Easy Setup
104
- Run the automatic configuration tool in your project root:
105
-
106
- ```bash
107
- npx viewgate-wrapper setup
108
- ```
109
-
110
- ### Manual Configuration
111
- Add this to your `claude_desktop_config.json` or Cursor MCP settings:
137
+ ### Configuration
138
+ The `npx viewgate-wrapper setup` command handles this for you. Manually, you can add this to your MCP settings:
112
139
 
113
140
  ```json
114
141
  {
@@ -117,7 +144,8 @@ Add this to your `claude_desktop_config.json` or Cursor MCP settings:
117
144
  "command": "npx",
118
145
  "args": ["-y", "viewgate-mcp@latest"],
119
146
  "env": {
120
- "VIEWGATE_API_KEY": "VG-YOUR-PROJECT-KEY"
147
+ "VIEWGATE_API_KEY": "VG-YOUR-PROJECT-KEY",
148
+ "VIEWGATE_PERSONAL_KEY": "YOUR-PERSONAL-KEY"
121
149
  }
122
150
  }
123
151
  }
@@ -127,21 +155,7 @@ Add this to your `claude_desktop_config.json` or Cursor MCP settings:
127
155
  ### ⚡ Example Commands
128
156
  Once configured, you can simply ask your AI assistant:
129
157
  - *"Read ViewGate annotations and apply the changes"*
130
- - *"Review UI feedback and resolve pending tasks"*
131
- - *"Apply ViewGate changes"*
132
-
133
- ---
134
-
135
-
136
- ## 💡 Troubleshooting
137
-
138
- ### Layering Issues (Z-Index)
139
- ViewGate's background elements (pins and selection highlights) are configured with a low `z-index` to avoid overlapping with your application's primary UI.
140
- - **Pins**: `50`
141
- - **Selection Highlights**: `100`
142
- - **Modals**: `2,000,000`
143
-
144
- If pins are appearing over your headers, ensure your app's headers have a `z-index` higher than `100`.
158
+ - *"Resolve UI feedback in this project"*
145
159
 
146
160
  ---
147
161
 
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import fs from 'fs';
3
3
  import path from 'path';
4
4
  import os from 'os';
5
5
  import { fileURLToPath } from 'url';
6
- import { detectFramework, injectVitePlugin, injectNextPlugin } from './plugin/config-injectors.js';
6
+ import { detectFramework, injectVitePlugin, injectNextPlugin, injectWebpackPlugin, injectBabelPlugin } from './plugin/config-injectors.js';
7
7
  const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = path.dirname(__filename);
9
9
  async function setup() {
@@ -16,8 +16,6 @@ async function setup() {
16
16
  process.exit(1);
17
17
  }
18
18
  // 2. Determine the path or URL
19
- // Since we now have a standalone server, we can point to its URL or local path.
20
- // The user wants it to be scalable, so we'll prioritize a server URL.
21
19
  const mcpServerUrl = process.env.MCP_SERVER_URL || 'https://view-gate-mcp.vercel.app/sse';
22
20
  // 3. Read and update mcp_config.json
23
21
  try {
@@ -27,8 +25,6 @@ async function setup() {
27
25
  }
28
26
  const currentServer = config.mcpServers.viewgate || {};
29
27
  const env = currentServer.env || {};
30
- // Default values if not present
31
- const backendUrl = env.BACKEND_URL || 'http://localhost:5000';
32
28
  const apiKey = env.API_KEY || '';
33
29
  config.mcpServers["viewgate"] = {
34
30
  command: "npx",
@@ -40,7 +36,6 @@ async function setup() {
40
36
  };
41
37
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
42
38
  console.log(`✅ Updated mcp_config.json successfully!`);
43
- console.log(`📍 MCP Server URL: ${mcpServerUrl}`);
44
39
  if (!apiKey || !env.VIEWGATE_PERSONAL_KEY) {
45
40
  console.log('\n⚠️ Recuerda configurar tus credenciales en:');
46
41
  console.log(` ${configPath}`);
@@ -55,7 +50,7 @@ async function setup() {
55
50
  const cwd = process.cwd();
56
51
  const result = detectFramework(cwd);
57
52
  if (result.framework === 'vite' && result.configPath) {
58
- console.log(`✨ Vite detected! Attempting to apply viewgatePlugin to: ${path.basename(result.configPath)}`);
53
+ console.log(`✨ Vite detected! Attempting to apply plugin to: ${path.basename(result.configPath)}`);
59
54
  if (injectVitePlugin(result.configPath)) {
60
55
  console.log('✅ viewgatePlugin applied successfully!');
61
56
  }
@@ -72,13 +67,53 @@ async function setup() {
72
67
  console.log('⚠️ Could not auto-apply plugin. Please follow manual setup in README.');
73
68
  }
74
69
  }
70
+ else if (result.framework === 'webpack' && result.configPath) {
71
+ console.log(`✨ Webpack/Craco detected! Attempting to apply loader to: ${path.basename(result.configPath)}`);
72
+ if (injectWebpackPlugin(result.configPath)) {
73
+ console.log('✅ webpack-loader applied successfully!');
74
+ }
75
+ else {
76
+ console.log('⚠️ Could not auto-apply loader. Please follow manual setup in README.');
77
+ }
78
+ }
79
+ else if (result.framework === 'babel' && result.configPath) {
80
+ console.log(`✨ Babel detected in: ${path.basename(result.configPath)}`);
81
+ if (injectBabelPlugin(result.configPath)) {
82
+ console.log('✅ babel-plugin applied successfully!');
83
+ }
84
+ else {
85
+ console.log('⚠️ Could not auto-apply plugin. Please follow manual setup in README.');
86
+ }
87
+ }
88
+ else if (result.framework === 'react-scripts') {
89
+ console.log('✨ Create React App (CRA) detected!');
90
+ console.log('👉 CRA doesn\'t allow easy config changes. ViewGate will use "Zero-Config" Fiber fallback.');
91
+ console.log('💡 For High-Precision mapping, consider using Craco: https://craco.js.org/');
92
+ }
93
+ else if (result.framework === 'astro' || result.framework === 'remix') {
94
+ console.log(`✨ ${result.framework.toUpperCase()} detected!`);
95
+ if (result.configPath) {
96
+ console.log(`Attempting to apply Vite-based plugin to: ${path.basename(result.configPath)}`);
97
+ if (injectVitePlugin(result.configPath)) {
98
+ console.log('✅ viewgatePlugin applied successfully!');
99
+ }
100
+ else {
101
+ console.log('⚠️ Could not auto-apply. Please see README for manual setup.');
102
+ }
103
+ }
104
+ else {
105
+ console.log('👉 Please follow manual setup in README to enable High-Precision mapping.');
106
+ }
107
+ }
75
108
  else if (result.framework !== 'unknown') {
76
109
  console.log(`✨ ${result.framework.toUpperCase()} detected!`);
77
- console.log(`👉 Please follow the manual setup for ${result.framework} in the README to enable High-Precision mapping.`);
110
+ console.log(`👉 Please follow the manual setup for ${result.framework} in the README.`);
78
111
  }
79
112
  else {
80
113
  console.log('❓ Could not determine framework. High-Precision mapping might require manual setup.');
114
+ console.log('💡 ViewGate will still work using the "Zero-Config" Fiber fallback in development.');
81
115
  }
116
+ console.log('\n🎉 Setup complete! You can now start using ViewGate in your project.');
82
117
  }
83
118
  catch (error) {
84
119
  console.error(`❌ Error updating configuration: ${error.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"ViewGateOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ViewGateOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AA2BnF,OAAO,wBAAwB,CAAC;AA21BhC,eAAO,MAAM,eAAe,EAAE,EA6tF7B,CAAC"}
1
+ {"version":3,"file":"ViewGateOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ViewGateOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AA2BnF,OAAO,wBAAwB,CAAC;AAw2BhC,eAAO,MAAM,eAAe,EAAE,EA6tF7B,CAAC"}
@@ -1,8 +1,11 @@
1
1
  export interface DetectionResult {
2
- framework: 'vite' | 'next' | 'webpack' | 'babel' | 'unknown';
2
+ framework: 'vite' | 'next' | 'webpack' | 'babel' | 'astro' | 'remix' | 'react-scripts' | 'unknown';
3
3
  configPath: string | undefined;
4
4
  }
5
5
  export declare function detectFramework(cwd: string): DetectionResult;
6
6
  export declare function injectVitePlugin(configPath: string): boolean;
7
7
  export declare function injectNextPlugin(configPath: string): boolean;
8
+ export declare function injectWebpackPlugin(configPath: string): boolean;
9
+ export declare function injectBabelPlugin(configPath: string): boolean;
10
+ export declare function injectBabelToPackageJson(pkgPath: string): boolean;
8
11
  //# sourceMappingURL=config-injectors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-injectors.d.ts","sourceRoot":"","sources":["../../src/plugin/config-injectors.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAC7D,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAwB5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAmC5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAiD5D"}
1
+ {"version":3,"file":"config-injectors.d.ts","sourceRoot":"","sources":["../../src/plugin/config-injectors.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;IACnG,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAmD5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAqC5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CA2C5D;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAqB/D;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAkC7D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgBjE"}
@@ -2,6 +2,7 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  export function detectFramework(cwd) {
4
4
  const files = fs.readdirSync(cwd);
5
+ // 1. Check for specific config files
5
6
  if (files.includes('vite.config.ts') || files.includes('vite.config.js') || files.includes('vite.config.mjs')) {
6
7
  const configPath = files.find(f => f.startsWith('vite.config.'));
7
8
  return { framework: 'vite', configPath: configPath ? path.join(cwd, configPath) : undefined };
@@ -10,6 +11,14 @@ export function detectFramework(cwd) {
10
11
  const configPath = files.find(f => f.startsWith('next.config.'));
11
12
  return { framework: 'next', configPath: configPath ? path.join(cwd, configPath) : undefined };
12
13
  }
14
+ if (files.includes('astro.config.mjs') || files.includes('astro.config.ts')) {
15
+ const configPath = files.find(f => f.startsWith('astro.config.'));
16
+ return { framework: 'astro', configPath: configPath ? path.join(cwd, configPath) : undefined };
17
+ }
18
+ if (files.includes('remix.config.js') || files.includes('remix.config.ts')) {
19
+ const configPath = files.find(f => f.startsWith('remix.config.'));
20
+ return { framework: 'remix', configPath: configPath ? path.join(cwd, configPath) : undefined };
21
+ }
13
22
  if (files.includes('webpack.config.js') || files.includes('craco.config.js')) {
14
23
  const configPath = files.find(f => f.startsWith('webpack.config.') || f.startsWith('craco.config.'));
15
24
  return { framework: 'webpack', configPath: configPath ? path.join(cwd, configPath) : undefined };
@@ -18,6 +27,26 @@ export function detectFramework(cwd) {
18
27
  const configPath = files.find(f => f.includes('babel'));
19
28
  return { framework: 'babel', configPath: configPath ? path.join(cwd, configPath) : undefined };
20
29
  }
30
+ // 2. Fallback to package.json analysis
31
+ if (files.includes('package.json')) {
32
+ try {
33
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
34
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
35
+ if (deps['react-scripts'])
36
+ return { framework: 'react-scripts', configPath: path.join(cwd, 'package.json') };
37
+ if (pkg.babel)
38
+ return { framework: 'babel', configPath: path.join(cwd, 'package.json') };
39
+ if (deps['next'])
40
+ return { framework: 'next', configPath: undefined };
41
+ if (deps['vite'])
42
+ return { framework: 'vite', configPath: undefined };
43
+ if (deps['astro'])
44
+ return { framework: 'astro', configPath: undefined };
45
+ }
46
+ catch (e) {
47
+ // Ignore JSON errors
48
+ }
49
+ }
21
50
  return { framework: 'unknown', configPath: undefined };
22
51
  }
23
52
  export function injectVitePlugin(configPath) {
@@ -30,21 +59,24 @@ export function injectVitePlugin(configPath) {
30
59
  const isTS = configPath.endsWith('.ts');
31
60
  const isMJS = configPath.endsWith('.mjs');
32
61
  const importStatement = (isTS || isMJS || content.includes('import '))
33
- ? "\nimport viewgatePlugin from 'viewgate-wrapper/vite';\n"
34
- : "\nconst viewgatePlugin = require('viewgate-wrapper/vite');\n";
35
- content = importStatement + content;
62
+ ? "import viewgatePlugin from 'viewgate-wrapper/vite';\n"
63
+ : "const viewgatePlugin = require('viewgate-wrapper/vite');\n";
64
+ if (!content.includes('viewgate-wrapper/vite')) {
65
+ content = importStatement + content;
66
+ }
36
67
  // 3. Inject into plugins array
37
- // Matches: plugins: [ ... ] or plugins: [...]
38
- const pluginsRegex = /plugins\s*:\s*\[([^\]]*)\]/;
68
+ const pluginsRegex = /plugins\s*:\s*\[/;
39
69
  if (pluginsRegex.test(content)) {
40
- content = content.replace(pluginsRegex, (match, p1) => {
41
- const trailingComma = p1.trim() && !p1.trim().endsWith(',') ? ',' : '';
42
- return `plugins: [\n viewgatePlugin(),${p1}${trailingComma}\n ]`;
43
- });
70
+ content = content.replace(pluginsRegex, `plugins: [\n viewgatePlugin(),`);
44
71
  }
45
72
  else {
46
- // If no plugins array found, we skip auto-injection to avoid breaking complex configs
47
- return false;
73
+ const configObjectRegex = /(defineConfig\s*\(\s*(?:{[^}]*}|(?:\([^)]*\)\s*=>\s*\(?))?\s*{)/;
74
+ if (configObjectRegex.test(content)) {
75
+ content = content.replace(configObjectRegex, `$1\n plugins: [viewgatePlugin()],`);
76
+ }
77
+ else {
78
+ return false;
79
+ }
48
80
  }
49
81
  fs.writeFileSync(configPath, content);
50
82
  return true;
@@ -55,47 +87,116 @@ export function injectVitePlugin(configPath) {
55
87
  }
56
88
  export function injectNextPlugin(configPath) {
57
89
  try {
90
+ // If no configPath, we might want to create a default one, but for now we bail
91
+ if (!configPath)
92
+ return false;
58
93
  let content = fs.readFileSync(configPath, 'utf8');
59
- // 1. Check if already injected
60
94
  if (content.includes('viewgate-wrapper/next-loader'))
61
95
  return true;
62
- // 2. Find nextConfig object and add webpack property
63
- // This is a bit more complex, we'll suggest manual setup if it's too nested
64
- // Simple detection: check if NEXT_PUBLIC_VIEWGATE_API_KEY is mentioned
65
- const webpackSnippet = `
66
- webpack: (config) => {
67
- config.module.rules.push({
96
+ const loaderConfig = `{
68
97
  test: /\\.(js|jsx|ts|tsx)$/,
98
+ exclude: /node_modules/,
69
99
  use: ['viewgate-wrapper/next-loader'],
70
- });
100
+ }`;
101
+ const webpackSnippet = `\n webpack: (config) => {
102
+ config.module.rules.push(${loaderConfig});
71
103
  return config;
72
104
  },`;
73
- // Try to find the export default or module.exports nextConfig
74
- if (content.includes('export default nextConfig')) {
75
- content = content.replace('export default nextConfig', `nextConfig.webpack = (config) => {
76
- config.module.rules.push({
77
- test: /\\.(js|jsx|ts|tsx)$/,
78
- use: ['viewgate-wrapper/next-loader'],
79
- });
80
- return config;
81
- };
82
- export default nextConfig;`);
105
+ const anonymousExportRegex = /(module\.exports\s*=\s*|export\s*default\s*)\{/;
106
+ const nextConfigVarRegex = /(const|let|var)\s+(\w+)\s*=\s*\{/;
107
+ const nextConfigMatch = content.match(nextConfigVarRegex);
108
+ if (nextConfigMatch) {
109
+ const varName = nextConfigMatch[2];
110
+ const exportRegex = new RegExp(`(?:module\\.exports\\s*=\\s*|export\\s*default\\s*)${varName}`, 'm');
111
+ if (exportRegex.test(content)) {
112
+ content = content.replace(nextConfigVarRegex, `$1 $2 = {${webpackSnippet}`);
113
+ fs.writeFileSync(configPath, content);
114
+ return true;
115
+ }
116
+ }
117
+ if (anonymousExportRegex.test(content)) {
118
+ content = content.replace(anonymousExportRegex, `$1 {${webpackSnippet}`);
119
+ fs.writeFileSync(configPath, content);
120
+ return true;
83
121
  }
84
- else if (content.includes('module.exports = nextConfig')) {
85
- content = content.replace('module.exports = nextConfig', `nextConfig.webpack = (config) => {
86
- config.module.rules.push({
87
- test: /\\.(js|jsx|ts|tsx)$/,
88
- use: ['viewgate-wrapper/next-loader'],
89
- });
90
- return config;
91
- };
92
- module.exports = nextConfig;`);
122
+ return false;
123
+ }
124
+ catch (e) {
125
+ return false;
126
+ }
127
+ }
128
+ export function injectWebpackPlugin(configPath) {
129
+ try {
130
+ let content = fs.readFileSync(configPath, 'utf8');
131
+ if (content.includes('viewgate-wrapper/webpack-loader'))
132
+ return true;
133
+ const loaderConfig = `{
134
+ test: /\\.(js|jsx|ts|tsx)$/,
135
+ exclude: /node_modules/,
136
+ use: ['viewgate-wrapper/webpack-loader'],
137
+ }`;
138
+ const rulesRegex = /rules\s*:\s*\[/;
139
+ if (rulesRegex.test(content)) {
140
+ content = content.replace(rulesRegex, `rules: [\n ${loaderConfig},`);
141
+ fs.writeFileSync(configPath, content);
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ catch (e) {
147
+ return false;
148
+ }
149
+ }
150
+ export function injectBabelPlugin(configPath) {
151
+ try {
152
+ const isPackageJson = configPath.endsWith('package.json');
153
+ if (isPackageJson)
154
+ return injectBabelToPackageJson(configPath);
155
+ const isJson = configPath.endsWith('.json') || configPath.includes('.babelrc');
156
+ let content = fs.readFileSync(configPath, 'utf8');
157
+ if (content.includes('viewgate-wrapper/babel'))
158
+ return true;
159
+ if (isJson) {
160
+ try {
161
+ const config = JSON.parse(content);
162
+ if (!config.plugins)
163
+ config.plugins = [];
164
+ if (!config.plugins.includes('viewgate-wrapper/babel')) {
165
+ config.plugins.push('viewgate-wrapper/babel');
166
+ }
167
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
168
+ return true;
169
+ }
170
+ catch {
171
+ return false;
172
+ }
93
173
  }
94
174
  else {
95
- // Too complex to auto-inject reliably
96
- return false;
175
+ const pluginsRegex = /plugins\s*:\s*\[/;
176
+ if (pluginsRegex.test(content)) {
177
+ content = content.replace(pluginsRegex, `plugins: [\n 'viewgate-wrapper/babel',`);
178
+ fs.writeFileSync(configPath, content);
179
+ return true;
180
+ }
181
+ }
182
+ return false;
183
+ }
184
+ catch (e) {
185
+ return false;
186
+ }
187
+ }
188
+ export function injectBabelToPackageJson(pkgPath) {
189
+ try {
190
+ const content = fs.readFileSync(pkgPath, 'utf8');
191
+ const pkg = JSON.parse(content);
192
+ if (!pkg.babel)
193
+ pkg.babel = {};
194
+ if (!pkg.babel.plugins)
195
+ pkg.babel.plugins = [];
196
+ if (!pkg.babel.plugins.includes('viewgate-wrapper/babel')) {
197
+ pkg.babel.plugins.push('viewgate-wrapper/babel');
198
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
97
199
  }
98
- fs.writeFileSync(configPath, content);
99
200
  return true;
100
201
  }
101
202
  catch (e) {