viewgate-wrapper 1.11.28 → 1.11.30
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 +59 -45
- package/dist/cli.js +43 -8
- package/dist/components/ViewGateOverlay.d.ts.map +1 -1
- package/dist/components/ViewGateProvider.d.ts +8 -0
- package/dist/components/ViewGateProvider.d.ts.map +1 -1
- package/dist/plugin/config-injectors.d.ts +4 -1
- package/dist/plugin/config-injectors.d.ts.map +1 -1
- package/dist/plugin/config-injectors.js +142 -41
- package/dist/viewgate-wrapper.js +1914 -1771
- package/dist/viewgate-wrapper.umd.cjs +12 -12
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,15 +11,26 @@ npm install viewgate-wrapper
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
## 🚀
|
|
14
|
+
## 🚀 Quick Setup (Automatic)
|
|
15
15
|
|
|
16
|
-
ViewGate
|
|
16
|
+
The easiest way to configure ViewGate for **High-Precision Mapping** and **AI Automation** is using our CLI tool:
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
### 📦
|
|
33
|
-
Add the loader to your `
|
|
43
|
+
### 📦 Next.js
|
|
44
|
+
Add the loader to your `next.config.js` or `next.config.mjs`:
|
|
34
45
|
|
|
35
46
|
```javascript
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
/** @type {import('next').NextConfig} */
|
|
48
|
+
const nextConfig = {
|
|
38
49
|
webpack: (config) => {
|
|
39
50
|
config.module.rules.push({
|
|
40
|
-
test: /\.(
|
|
51
|
+
test: /\.(js|jsx|ts|tsx)$/,
|
|
41
52
|
exclude: /node_modules/,
|
|
42
|
-
use: [
|
|
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
|
-
|
|
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/
|
|
84
|
+
"plugins": ["viewgate-wrapper/babel"]
|
|
55
85
|
}
|
|
56
86
|
```
|
|
57
87
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
>
|
|
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
|
-
###
|
|
104
|
-
|
|
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
|
-
- *"
|
|
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
|
|
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
|
|
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;
|
|
1
|
+
{"version":3,"file":"ViewGateOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ViewGateOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AA8BnF,OAAO,wBAAwB,CAAC;AAw2BhC,eAAO,MAAM,eAAe,EAAE,EA+1F7B,CAAC"}
|
|
@@ -70,6 +70,10 @@ declare const translations: {
|
|
|
70
70
|
figmaLinkPlaceholder: string;
|
|
71
71
|
endpoint: string;
|
|
72
72
|
selectEndpoint: string;
|
|
73
|
+
figmaNamePlaceholder: string;
|
|
74
|
+
addLink: string;
|
|
75
|
+
removeLink: string;
|
|
76
|
+
figmaPrimaryDesign: string;
|
|
73
77
|
};
|
|
74
78
|
es: {
|
|
75
79
|
enterMode: string;
|
|
@@ -139,6 +143,10 @@ declare const translations: {
|
|
|
139
143
|
figmaLinkPlaceholder: string;
|
|
140
144
|
endpoint: string;
|
|
141
145
|
selectEndpoint: string;
|
|
146
|
+
figmaNamePlaceholder: string;
|
|
147
|
+
addLink: string;
|
|
148
|
+
removeLink: string;
|
|
149
|
+
figmaPrimaryDesign: string;
|
|
142
150
|
};
|
|
143
151
|
};
|
|
144
152
|
export interface SemanticReference {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewGateProvider.d.ts","sourceRoot":"","sources":["../../src/components/ViewGateProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAA0D,KAAK,SAAS,EAAE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAIxG,OAAO,wBAAwB,CAAC;AAEhC,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,QAAA,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"ViewGateProvider.d.ts","sourceRoot":"","sources":["../../src/components/ViewGateProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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
|
-
? "
|
|
34
|
-
: "
|
|
35
|
-
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
|
-
|
|
38
|
-
const pluginsRegex = /plugins\s*:\s*\[([^\]]*)\]/;
|
|
68
|
+
const pluginsRegex = /plugins\s*:\s*\[/;
|
|
39
69
|
if (pluginsRegex.test(content)) {
|
|
40
|
-
content = content.replace(pluginsRegex, (
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
96
|
-
|
|
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) {
|