@rayburst/cli 0.1.18 → 0.2.1
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 +165 -257
- package/dist/chunk-NIOHEIF6.js +722 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +24 -0
- package/dist/vite-plugin.d.ts +10 -0
- package/dist/vite-plugin.js +6 -0
- package/package.json +37 -25
- package/bin/rayburst.js +0 -216
- package/index.html +0 -54
- package/scripts/analyze-project.js +0 -475
- package/server.js +0 -147
- package/src/file-watcher.js +0 -174
- package/src/git-utils.js +0 -105
- package/src/incremental-analyzer.js +0 -295
- package/src/main.tsx +0 -225
- package/src/registry.js +0 -262
- package/vite-plugin-api.js +0 -123
- package/vite.config.ts +0 -72
package/src/main.tsx
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import React, { Suspense, lazy, useEffect, useState } from 'react';
|
|
2
|
-
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import * as ReactDOM from 'react-dom/client';
|
|
4
|
-
|
|
5
|
-
// Expose React and ReactDOM globally for module federation
|
|
6
|
-
(window as any).React = React;
|
|
7
|
-
(window as any).ReactDOM = ReactDOM;
|
|
8
|
-
|
|
9
|
-
// Loading component
|
|
10
|
-
const LoadingFallback = () => (
|
|
11
|
-
<div style={{
|
|
12
|
-
display: 'flex',
|
|
13
|
-
flexDirection: 'column',
|
|
14
|
-
alignItems: 'center',
|
|
15
|
-
justifyContent: 'center',
|
|
16
|
-
height: '100vh',
|
|
17
|
-
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
18
|
-
color: 'white',
|
|
19
|
-
}}>
|
|
20
|
-
<div style={{
|
|
21
|
-
width: '50px',
|
|
22
|
-
height: '50px',
|
|
23
|
-
border: '4px solid rgba(255, 255, 255, 0.3)',
|
|
24
|
-
borderTopColor: 'white',
|
|
25
|
-
borderRadius: '50%',
|
|
26
|
-
animation: 'spin 1s linear infinite',
|
|
27
|
-
marginBottom: '20px',
|
|
28
|
-
}} />
|
|
29
|
-
<div style={{ fontSize: '18px', fontWeight: 500 }}>Loading Rayburst...</div>
|
|
30
|
-
</div>
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
// Error boundary component
|
|
34
|
-
class ErrorBoundary extends React.Component<
|
|
35
|
-
{ children: React.ReactNode },
|
|
36
|
-
{ hasError: boolean; error: Error | null }
|
|
37
|
-
> {
|
|
38
|
-
constructor(props: { children: React.ReactNode }) {
|
|
39
|
-
super(props);
|
|
40
|
-
this.state = { hasError: false, error: null };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static getDerivedStateFromError(error: Error) {
|
|
44
|
-
return { hasError: true, error };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
48
|
-
console.error('Remote app loading error:', error, errorInfo);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
render() {
|
|
52
|
-
if (this.state.hasError) {
|
|
53
|
-
return (
|
|
54
|
-
<div style={{
|
|
55
|
-
display: 'flex',
|
|
56
|
-
flexDirection: 'column',
|
|
57
|
-
alignItems: 'center',
|
|
58
|
-
justifyContent: 'center',
|
|
59
|
-
height: '100vh',
|
|
60
|
-
background: '#f5f5f5',
|
|
61
|
-
padding: '20px',
|
|
62
|
-
}}>
|
|
63
|
-
<h1 style={{ color: '#d32f2f', marginBottom: '10px' }}>Failed to Load Rayburst</h1>
|
|
64
|
-
<p style={{ color: '#666', marginBottom: '20px' }}>
|
|
65
|
-
{this.state.error?.message || 'An unexpected error occurred'}
|
|
66
|
-
</p>
|
|
67
|
-
<button
|
|
68
|
-
onClick={() => window.location.reload()}
|
|
69
|
-
style={{
|
|
70
|
-
padding: '10px 20px',
|
|
71
|
-
background: '#667eea',
|
|
72
|
-
color: 'white',
|
|
73
|
-
border: 'none',
|
|
74
|
-
borderRadius: '5px',
|
|
75
|
-
cursor: 'pointer',
|
|
76
|
-
fontSize: '16px',
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
79
|
-
Retry
|
|
80
|
-
</button>
|
|
81
|
-
</div>
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return this.props.children;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Function to load remote CSS
|
|
90
|
-
const loadRemoteCSS = async () => {
|
|
91
|
-
try {
|
|
92
|
-
// Determine the remote URL based on environment
|
|
93
|
-
const isDevelopment = import.meta.env.DEV;
|
|
94
|
-
const remoteUrl = isDevelopment
|
|
95
|
-
? 'http://localhost:3000'
|
|
96
|
-
: import.meta.env.PROD
|
|
97
|
-
? 'https://www.rayburst.app'
|
|
98
|
-
: 'https://dev.rayburst.app';
|
|
99
|
-
|
|
100
|
-
console.log('[CLI] Attempting to load CSS from:', remoteUrl, '(dev mode:', isDevelopment, ')');
|
|
101
|
-
|
|
102
|
-
if (isDevelopment) {
|
|
103
|
-
// In development mode, Vite serves CSS as a JavaScript module
|
|
104
|
-
// We need to dynamically import it to trigger Vite's CSS injection
|
|
105
|
-
console.log('[CLI] Development mode: Importing CSS module from Vite dev server');
|
|
106
|
-
|
|
107
|
-
const cssModuleUrl = `${remoteUrl}/src/styles.css`;
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
// Check if we've already loaded this CSS module
|
|
111
|
-
if (!(window as any).__rayburstCssLoaded) {
|
|
112
|
-
console.log('[CLI] Dynamically importing CSS module:', cssModuleUrl);
|
|
113
|
-
|
|
114
|
-
// Create a script tag to load the CSS module
|
|
115
|
-
const script = document.createElement('script');
|
|
116
|
-
script.type = 'module';
|
|
117
|
-
script.textContent = `import '${cssModuleUrl}';`;
|
|
118
|
-
document.head.appendChild(script);
|
|
119
|
-
|
|
120
|
-
// Mark as loaded
|
|
121
|
-
(window as any).__rayburstCssLoaded = true;
|
|
122
|
-
console.log('[CLI] CSS module import initiated');
|
|
123
|
-
|
|
124
|
-
// Give it a moment to process
|
|
125
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
126
|
-
} else {
|
|
127
|
-
console.log('[CLI] CSS module already loaded');
|
|
128
|
-
}
|
|
129
|
-
} catch (cssErr) {
|
|
130
|
-
console.warn('[CLI] Could not load CSS module, styles may be missing:', cssErr);
|
|
131
|
-
}
|
|
132
|
-
} else {
|
|
133
|
-
// In production/staging, fetch the index.html to find the CSS file
|
|
134
|
-
const response = await fetch(remoteUrl);
|
|
135
|
-
const html = await response.text();
|
|
136
|
-
|
|
137
|
-
// Extract CSS filename from the HTML
|
|
138
|
-
const cssMatch = html.match(/href="\/assets\/(style-[^"]+\.css)"/);
|
|
139
|
-
|
|
140
|
-
if (cssMatch && cssMatch[1]) {
|
|
141
|
-
const cssFile = cssMatch[1];
|
|
142
|
-
const cssUrl = `${remoteUrl}/assets/${cssFile}`;
|
|
143
|
-
|
|
144
|
-
console.log('[CLI] Loading remote CSS:', cssUrl);
|
|
145
|
-
|
|
146
|
-
// Check if CSS is already loaded
|
|
147
|
-
const existingLink = document.querySelector(`link[href="${cssUrl}"]`);
|
|
148
|
-
if (!existingLink) {
|
|
149
|
-
const link = document.createElement('link');
|
|
150
|
-
link.rel = 'stylesheet';
|
|
151
|
-
link.href = cssUrl;
|
|
152
|
-
document.head.appendChild(link);
|
|
153
|
-
console.log('[CLI] Remote CSS loaded successfully');
|
|
154
|
-
|
|
155
|
-
// Wait for CSS to load
|
|
156
|
-
await new Promise((resolve) => {
|
|
157
|
-
link.onload = resolve;
|
|
158
|
-
link.onerror = resolve;
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
console.warn('[CLI] No CSS file found in remote HTML');
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
console.error('[CLI] Failed to load remote CSS:', err);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// Dynamically import the remote app
|
|
171
|
-
const RemoteApp = lazy(async () => {
|
|
172
|
-
console.log('[CLI] Attempting to load remote app from rayburstApp/App');
|
|
173
|
-
console.log('[CLI] Expected remote URL:', 'http://localhost:3000/remoteEntry.js');
|
|
174
|
-
|
|
175
|
-
// Load the remote CSS first (in parallel with module loading)
|
|
176
|
-
const cssPromise = loadRemoteCSS();
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
// @ts-ignore - Module federation import
|
|
180
|
-
const module = await import('rayburstApp/App');
|
|
181
|
-
console.log('[CLI] Successfully loaded remote app module:', module);
|
|
182
|
-
|
|
183
|
-
// Wait for CSS to finish loading
|
|
184
|
-
await cssPromise;
|
|
185
|
-
|
|
186
|
-
return module;
|
|
187
|
-
} catch (err: any) {
|
|
188
|
-
console.error('[CLI] Failed to load remote app:', err);
|
|
189
|
-
console.error('[CLI] Error details:', {
|
|
190
|
-
name: err.name,
|
|
191
|
-
message: err.message,
|
|
192
|
-
stack: err.stack
|
|
193
|
-
});
|
|
194
|
-
throw new Error('Could not load Rayburst application. Make sure it is running on port 3000.');
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
function App() {
|
|
199
|
-
const [isReady, setIsReady] = useState(false);
|
|
200
|
-
|
|
201
|
-
useEffect(() => {
|
|
202
|
-
// Small delay to ensure remote is ready
|
|
203
|
-
const timer = setTimeout(() => setIsReady(true), 100);
|
|
204
|
-
return () => clearTimeout(timer);
|
|
205
|
-
}, []);
|
|
206
|
-
|
|
207
|
-
if (!isReady) {
|
|
208
|
-
return <LoadingFallback />;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return (
|
|
212
|
-
<ErrorBoundary>
|
|
213
|
-
<Suspense fallback={<LoadingFallback />}>
|
|
214
|
-
<RemoteApp />
|
|
215
|
-
</Suspense>
|
|
216
|
-
</ErrorBoundary>
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Mount the app
|
|
221
|
-
const container = document.getElementById('app');
|
|
222
|
-
if (container) {
|
|
223
|
-
const root = createRoot(container);
|
|
224
|
-
root.render(<App />);
|
|
225
|
-
}
|
package/src/registry.js
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
|
-
|
|
10
|
-
// Global rayburst directory in user's home
|
|
11
|
-
const RAYBURST_DIR = path.join(os.homedir(), '.rayburst');
|
|
12
|
-
const PROJECTS_FILE = path.join(RAYBURST_DIR, 'projects.json');
|
|
13
|
-
const ANALYZED_DIR = path.join(RAYBURST_DIR, 'analyzed');
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Ensure the .rayburst directory and subdirectories exist
|
|
17
|
-
*/
|
|
18
|
-
export function ensureRayburstDir() {
|
|
19
|
-
if (!fs.existsSync(RAYBURST_DIR)) {
|
|
20
|
-
fs.mkdirSync(RAYBURST_DIR, { recursive: true });
|
|
21
|
-
}
|
|
22
|
-
if (!fs.existsSync(ANALYZED_DIR)) {
|
|
23
|
-
fs.mkdirSync(ANALYZED_DIR, { recursive: true });
|
|
24
|
-
}
|
|
25
|
-
if (!fs.existsSync(PROJECTS_FILE)) {
|
|
26
|
-
fs.writeFileSync(PROJECTS_FILE, JSON.stringify({ projects: [] }, null, 2));
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Read the projects registry
|
|
32
|
-
*/
|
|
33
|
-
export function readRegistry() {
|
|
34
|
-
ensureRayburstDir();
|
|
35
|
-
try {
|
|
36
|
-
const data = fs.readFileSync(PROJECTS_FILE, 'utf-8');
|
|
37
|
-
return JSON.parse(data);
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error('Error reading registry:', error.message);
|
|
40
|
-
return { projects: [] };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Write to the projects registry
|
|
46
|
-
*/
|
|
47
|
-
export function writeRegistry(registry) {
|
|
48
|
-
ensureRayburstDir();
|
|
49
|
-
try {
|
|
50
|
-
fs.writeFileSync(PROJECTS_FILE, JSON.stringify(registry, null, 2));
|
|
51
|
-
return true;
|
|
52
|
-
} catch (error) {
|
|
53
|
-
console.error('Error writing registry:', error.message);
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Generate a unique project ID from the project path
|
|
60
|
-
*/
|
|
61
|
-
export function generateProjectId(projectPath) {
|
|
62
|
-
const hash = crypto.createHash('md5').update(projectPath).digest('hex');
|
|
63
|
-
return hash.substring(0, 12);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Check if a directory is a valid project (has package.json)
|
|
68
|
-
*/
|
|
69
|
-
export function isValidProject(projectPath) {
|
|
70
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
71
|
-
return fs.existsSync(packageJsonPath);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Read package.json from a project
|
|
76
|
-
*/
|
|
77
|
-
export function readPackageJson(projectPath) {
|
|
78
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
79
|
-
try {
|
|
80
|
-
const data = fs.readFileSync(packageJsonPath, 'utf-8');
|
|
81
|
-
return JSON.parse(data);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error(`Error reading package.json:`, error.message);
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Register a new project
|
|
90
|
-
*/
|
|
91
|
-
export function registerProject(projectPath) {
|
|
92
|
-
const absolutePath = path.resolve(projectPath);
|
|
93
|
-
|
|
94
|
-
// Validate project
|
|
95
|
-
if (!isValidProject(absolutePath)) {
|
|
96
|
-
throw new Error(`Not a valid project: ${absolutePath} (missing package.json)`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const registry = readRegistry();
|
|
100
|
-
const projectId = generateProjectId(absolutePath);
|
|
101
|
-
|
|
102
|
-
// Check if already registered
|
|
103
|
-
const existingIndex = registry.projects.findIndex(p => p.id === projectId);
|
|
104
|
-
if (existingIndex >= 0) {
|
|
105
|
-
throw new Error(`Project already registered: ${absolutePath}`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Read package.json
|
|
109
|
-
const packageJson = readPackageJson(absolutePath);
|
|
110
|
-
if (!packageJson) {
|
|
111
|
-
throw new Error(`Failed to read package.json from ${absolutePath}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Create project entry
|
|
115
|
-
const project = {
|
|
116
|
-
id: projectId,
|
|
117
|
-
name: packageJson.name || path.basename(absolutePath),
|
|
118
|
-
path: absolutePath,
|
|
119
|
-
registeredAt: new Date().toISOString(),
|
|
120
|
-
lastAnalyzed: null,
|
|
121
|
-
packageJson: {
|
|
122
|
-
name: packageJson.name,
|
|
123
|
-
version: packageJson.version,
|
|
124
|
-
description: packageJson.description,
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
registry.projects.push(project);
|
|
129
|
-
|
|
130
|
-
if (writeRegistry(registry)) {
|
|
131
|
-
return project;
|
|
132
|
-
} else {
|
|
133
|
-
throw new Error('Failed to write registry');
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Unregister a project
|
|
139
|
-
*/
|
|
140
|
-
export function unregisterProject(projectPathOrId) {
|
|
141
|
-
const registry = readRegistry();
|
|
142
|
-
const absolutePath = path.resolve(projectPathOrId);
|
|
143
|
-
const projectId = generateProjectId(absolutePath);
|
|
144
|
-
|
|
145
|
-
// Find by ID or path
|
|
146
|
-
const index = registry.projects.findIndex(
|
|
147
|
-
p => p.id === projectId || p.id === projectPathOrId || p.path === absolutePath
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
if (index === -1) {
|
|
151
|
-
throw new Error(`Project not found: ${projectPathOrId}`);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const project = registry.projects[index];
|
|
155
|
-
registry.projects.splice(index, 1);
|
|
156
|
-
|
|
157
|
-
// Remove analysis data if it exists
|
|
158
|
-
const analysisFile = path.join(ANALYZED_DIR, `${project.id}.json`);
|
|
159
|
-
if (fs.existsSync(analysisFile)) {
|
|
160
|
-
fs.unlinkSync(analysisFile);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (writeRegistry(registry)) {
|
|
164
|
-
return project;
|
|
165
|
-
} else {
|
|
166
|
-
throw new Error('Failed to write registry');
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* List all registered projects
|
|
172
|
-
*/
|
|
173
|
-
export function listProjects() {
|
|
174
|
-
const registry = readRegistry();
|
|
175
|
-
return registry.projects;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Get a specific project by ID or path
|
|
180
|
-
*/
|
|
181
|
-
export function getProject(projectIdOrPath) {
|
|
182
|
-
const registry = readRegistry();
|
|
183
|
-
const absolutePath = path.resolve(projectIdOrPath);
|
|
184
|
-
const projectId = generateProjectId(absolutePath);
|
|
185
|
-
|
|
186
|
-
return registry.projects.find(
|
|
187
|
-
p => p.id === projectId || p.id === projectIdOrPath || p.path === absolutePath
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Update project's lastAnalyzed timestamp
|
|
193
|
-
*/
|
|
194
|
-
export function updateProjectAnalysis(projectId) {
|
|
195
|
-
const registry = readRegistry();
|
|
196
|
-
const project = registry.projects.find(p => p.id === projectId);
|
|
197
|
-
|
|
198
|
-
if (!project) {
|
|
199
|
-
throw new Error(`Project not found: ${projectId}`);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
project.lastAnalyzed = new Date().toISOString();
|
|
203
|
-
|
|
204
|
-
if (writeRegistry(registry)) {
|
|
205
|
-
return project;
|
|
206
|
-
} else {
|
|
207
|
-
throw new Error('Failed to update registry');
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Get path to analysis file for a project
|
|
213
|
-
*/
|
|
214
|
-
export function getAnalysisFilePath(projectId) {
|
|
215
|
-
return path.join(ANALYZED_DIR, `${projectId}.json`);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Read analysis data for a project
|
|
220
|
-
*/
|
|
221
|
-
export function readAnalysisData(projectId) {
|
|
222
|
-
const analysisFile = getAnalysisFilePath(projectId);
|
|
223
|
-
|
|
224
|
-
if (!fs.existsSync(analysisFile)) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
try {
|
|
229
|
-
const data = fs.readFileSync(analysisFile, 'utf-8');
|
|
230
|
-
return JSON.parse(data);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
console.error(`Error reading analysis data:`, error.message);
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Write analysis data for a project
|
|
239
|
-
*/
|
|
240
|
-
export function writeAnalysisData(projectId, analysisData) {
|
|
241
|
-
ensureRayburstDir();
|
|
242
|
-
const analysisFile = getAnalysisFilePath(projectId);
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
fs.writeFileSync(analysisFile, JSON.stringify(analysisData, null, 2));
|
|
246
|
-
return true;
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error(`Error writing analysis data:`, error.message);
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Get registry paths for external access
|
|
255
|
-
*/
|
|
256
|
-
export function getRegistryPaths() {
|
|
257
|
-
return {
|
|
258
|
-
rayburstDir: RAYBURST_DIR,
|
|
259
|
-
projectsFile: PROJECTS_FILE,
|
|
260
|
-
analyzedDir: ANALYZED_DIR,
|
|
261
|
-
};
|
|
262
|
-
}
|
package/vite-plugin-api.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listProjects,
|
|
3
|
-
getProject,
|
|
4
|
-
readAnalysisData,
|
|
5
|
-
registerProject,
|
|
6
|
-
unregisterProject,
|
|
7
|
-
} from './src/registry.js';
|
|
8
|
-
import { getAllChangedFiles } from './src/git-utils.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Vite plugin to handle API routes during development
|
|
12
|
-
*/
|
|
13
|
-
export function apiPlugin() {
|
|
14
|
-
return {
|
|
15
|
-
name: 'rayburst-api',
|
|
16
|
-
configureServer(server) {
|
|
17
|
-
server.middlewares.use('/api', (req, res, next) => {
|
|
18
|
-
// Parse JSON body for POST requests
|
|
19
|
-
if (req.method === 'POST' || req.method === 'PUT') {
|
|
20
|
-
let body = '';
|
|
21
|
-
req.on('data', chunk => {
|
|
22
|
-
body += chunk.toString();
|
|
23
|
-
});
|
|
24
|
-
req.on('end', () => {
|
|
25
|
-
try {
|
|
26
|
-
req.body = JSON.parse(body);
|
|
27
|
-
} catch (e) {
|
|
28
|
-
req.body = {};
|
|
29
|
-
}
|
|
30
|
-
handleApiRequest(req, res, next);
|
|
31
|
-
});
|
|
32
|
-
} else {
|
|
33
|
-
handleApiRequest(req, res, next);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function handleApiRequest(req, res, next) {
|
|
41
|
-
const url = (req.url || '').replace('/api', ''); // Remove /api prefix since middleware already matched it
|
|
42
|
-
const method = req.method;
|
|
43
|
-
|
|
44
|
-
// Set JSON response headers
|
|
45
|
-
res.setHeader('Content-Type', 'application/json');
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
// GET /api/projects - List all projects
|
|
49
|
-
if (method === 'GET' && url === '/projects') {
|
|
50
|
-
const projects = listProjects();
|
|
51
|
-
res.end(JSON.stringify({ projects }));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// GET /projects/:id/changed-files - Get uncommitted changed files (check before generic project route)
|
|
56
|
-
if (method === 'GET' && url.includes('/changed-files')) {
|
|
57
|
-
const id = url.split('/')[2];
|
|
58
|
-
const project = getProject(id);
|
|
59
|
-
if (!project) {
|
|
60
|
-
res.statusCode = 404;
|
|
61
|
-
res.end(JSON.stringify({ error: 'Project not found' }));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const changedFiles = getAllChangedFiles(project.path);
|
|
65
|
-
res.end(JSON.stringify({ changedFiles }));
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// GET /projects/:id/analysis - Get project analysis
|
|
70
|
-
if (method === 'GET' && url.includes('/analysis')) {
|
|
71
|
-
const id = url.split('/')[2];
|
|
72
|
-
const analysisData = readAnalysisData(id);
|
|
73
|
-
if (!analysisData) {
|
|
74
|
-
res.statusCode = 404;
|
|
75
|
-
res.end(JSON.stringify({ error: 'Analysis data not found' }));
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
res.end(JSON.stringify(analysisData));
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// GET /projects/:id - Get specific project
|
|
83
|
-
if (method === 'GET' && url.startsWith('/projects/') && !url.includes('/analysis') && !url.includes('/changed-files')) {
|
|
84
|
-
const id = url.split('/')[2];
|
|
85
|
-
const project = getProject(id);
|
|
86
|
-
if (!project) {
|
|
87
|
-
res.statusCode = 404;
|
|
88
|
-
res.end(JSON.stringify({ error: 'Project not found' }));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
res.end(JSON.stringify({ project }));
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// POST /projects/register - Register project
|
|
96
|
-
if (method === 'POST' && url === '/projects/register') {
|
|
97
|
-
const { path } = req.body || {};
|
|
98
|
-
if (!path) {
|
|
99
|
-
res.statusCode = 400;
|
|
100
|
-
res.end(JSON.stringify({ error: 'Path is required' }));
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const project = registerProject(path);
|
|
104
|
-
res.end(JSON.stringify({ project }));
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// DELETE /projects/:id - Unregister project
|
|
109
|
-
if (method === 'DELETE' && url.startsWith('/projects/')) {
|
|
110
|
-
const id = url.split('/')[2];
|
|
111
|
-
const project = unregisterProject(id);
|
|
112
|
-
res.end(JSON.stringify({ project }));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// No matching route
|
|
117
|
-
res.statusCode = 404;
|
|
118
|
-
res.end(JSON.stringify({ error: 'API endpoint not found' }));
|
|
119
|
-
} catch (error) {
|
|
120
|
-
res.statusCode = 500;
|
|
121
|
-
res.end(JSON.stringify({ error: error.message }));
|
|
122
|
-
}
|
|
123
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
import react from '@vitejs/plugin-react';
|
|
3
|
-
import { federation } from '@module-federation/vite';
|
|
4
|
-
import { apiPlugin } from './vite-plugin-api.js';
|
|
5
|
-
|
|
6
|
-
// Determine remote URL based on environment
|
|
7
|
-
function getRemoteUrl(env: string): string {
|
|
8
|
-
switch (env) {
|
|
9
|
-
case 'production':
|
|
10
|
-
return 'https://www.rayburst.app';
|
|
11
|
-
case 'staging':
|
|
12
|
-
return 'https://dev.rayburst.app';
|
|
13
|
-
case 'development':
|
|
14
|
-
default:
|
|
15
|
-
return 'http://localhost:3000';
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default defineConfig(() => {
|
|
20
|
-
const environment = process.env.NODE_ENV || 'development';
|
|
21
|
-
const remoteUrl = getRemoteUrl(environment);
|
|
22
|
-
|
|
23
|
-
console.log(`🔧 Building CLI for environment: ${environment}`);
|
|
24
|
-
console.log(`📡 Remote URL: ${remoteUrl}`);
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
plugins: [
|
|
28
|
-
apiPlugin(),
|
|
29
|
-
react(),
|
|
30
|
-
federation({
|
|
31
|
-
name: 'rayburstCli',
|
|
32
|
-
remotes: {
|
|
33
|
-
rayburstApp: {
|
|
34
|
-
type: 'module',
|
|
35
|
-
name: 'rayburstApp',
|
|
36
|
-
entry: `${remoteUrl}/remoteEntry.js?t=${Date.now()}`,
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
shared: {
|
|
40
|
-
react: {
|
|
41
|
-
singleton: true,
|
|
42
|
-
requiredVersion: '^19.0.0',
|
|
43
|
-
},
|
|
44
|
-
'react-dom': {
|
|
45
|
-
singleton: true,
|
|
46
|
-
requiredVersion: '^19.0.0',
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
}),
|
|
50
|
-
],
|
|
51
|
-
|
|
52
|
-
build: {
|
|
53
|
-
modulePreload: false,
|
|
54
|
-
target: 'esnext',
|
|
55
|
-
minify: false,
|
|
56
|
-
cssCodeSplit: false,
|
|
57
|
-
outDir: 'dist',
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
server: {
|
|
61
|
-
port: 3105,
|
|
62
|
-
strictPort: true,
|
|
63
|
-
host: true,
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
preview: {
|
|
67
|
-
port: 3105,
|
|
68
|
-
strictPort: true,
|
|
69
|
-
host: true,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
});
|