@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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export { RayburstPluginOptions, rayburstPlugin } from './vite-plugin.js';
|
|
2
|
+
import { AnalysisResult } from '@rayburst/types';
|
|
3
|
+
export { AnalysisResult } from '@rayburst/types';
|
|
4
|
+
import 'vite';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Analyze a TypeScript/React project and generate nodes/edges data
|
|
8
|
+
* @param {string} projectPath - Absolute path to project root
|
|
9
|
+
* @param {string} projectId - Project ID
|
|
10
|
+
* @param {function} onLog - Callback for logging
|
|
11
|
+
* @returns {Promise<AnalysisResult>} Analysis data with nodes and edges
|
|
12
|
+
*/
|
|
13
|
+
declare function analyzeProject(projectPath: string, projectId?: string, onLog?: (message: string) => void): Promise<AnalysisResult>;
|
|
14
|
+
|
|
15
|
+
interface ProjectMeta {
|
|
16
|
+
projectId: string;
|
|
17
|
+
projectName: string;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
cliVersion: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Ensures the .rayburst directory exists in the project
|
|
23
|
+
*/
|
|
24
|
+
declare function ensureRayburstDir(projectPath: string): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads analysis data from .rayburst/analysis.json
|
|
27
|
+
*/
|
|
28
|
+
declare function readLocalAnalysis(projectPath: string): Promise<AnalysisResult | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Writes analysis data to .rayburst/analysis.json
|
|
31
|
+
*/
|
|
32
|
+
declare function writeLocalAnalysis(projectPath: string, analysis: AnalysisResult): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Reads project metadata from .rayburst/meta.json
|
|
35
|
+
*/
|
|
36
|
+
declare function readLocalMeta(projectPath: string): Promise<ProjectMeta | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Writes project metadata to .rayburst/meta.json
|
|
39
|
+
*/
|
|
40
|
+
declare function writeLocalMeta(projectPath: string, meta: ProjectMeta): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Adds .rayburst/ entry to .gitignore if not already present
|
|
43
|
+
*/
|
|
44
|
+
declare function addGitignoreEntry(projectPath: string): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if a project has been initialized (has .rayburst directory)
|
|
47
|
+
*/
|
|
48
|
+
declare function isProjectInitialized(projectPath: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Initializes a project with .rayburst directory and metadata
|
|
51
|
+
*/
|
|
52
|
+
declare function initializeProject(projectPath: string, projectName: string, cliVersion: string): Promise<ProjectMeta>;
|
|
53
|
+
|
|
54
|
+
export { type ProjectMeta, addGitignoreEntry, analyzeProject, ensureRayburstDir, initializeProject, isProjectInitialized, readLocalAnalysis, readLocalMeta, writeLocalAnalysis, writeLocalMeta };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addGitignoreEntry,
|
|
3
|
+
analyzeProject,
|
|
4
|
+
ensureRayburstDir,
|
|
5
|
+
initializeProject,
|
|
6
|
+
isProjectInitialized,
|
|
7
|
+
rayburstPlugin,
|
|
8
|
+
readLocalAnalysis,
|
|
9
|
+
readLocalMeta,
|
|
10
|
+
writeLocalAnalysis,
|
|
11
|
+
writeLocalMeta
|
|
12
|
+
} from "./chunk-NIOHEIF6.js";
|
|
13
|
+
export {
|
|
14
|
+
addGitignoreEntry,
|
|
15
|
+
analyzeProject,
|
|
16
|
+
ensureRayburstDir,
|
|
17
|
+
initializeProject,
|
|
18
|
+
isProjectInitialized,
|
|
19
|
+
rayburstPlugin,
|
|
20
|
+
readLocalAnalysis,
|
|
21
|
+
readLocalMeta,
|
|
22
|
+
writeLocalAnalysis,
|
|
23
|
+
writeLocalMeta
|
|
24
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
interface RayburstPluginOptions {
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
debounceMs?: number;
|
|
6
|
+
outputPath?: string;
|
|
7
|
+
}
|
|
8
|
+
declare function rayburstPlugin(options?: RayburstPluginOptions): Plugin;
|
|
9
|
+
|
|
10
|
+
export { type RayburstPluginOptions, rayburstPlugin };
|
package/package.json
CHANGED
|
@@ -1,44 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rayburst/cli",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Rayburst
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Rayburst - Automatic code analysis for TypeScript/JavaScript projects via Vite plugin",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./vite": {
|
|
14
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
15
|
+
"import": "./dist/vite-plugin.js"
|
|
16
|
+
}
|
|
8
17
|
},
|
|
9
|
-
"
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
10
22
|
"scripts": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"start": "node server.js"
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch"
|
|
14
25
|
},
|
|
15
26
|
"keywords": [
|
|
16
27
|
"rayburst",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
28
|
+
"vite-plugin",
|
|
29
|
+
"code-analysis",
|
|
30
|
+
"typescript",
|
|
31
|
+
"javascript",
|
|
32
|
+
"dependency-graph"
|
|
19
33
|
],
|
|
20
34
|
"author": "",
|
|
21
35
|
"license": "MIT",
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"vite": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
22
44
|
"dependencies": {
|
|
45
|
+
"@rayburst/types": "^0.1.1",
|
|
23
46
|
"chalk": "^5.3.0",
|
|
24
|
-
"chokidar": "^4.0.3",
|
|
25
|
-
"commander": "^11.1.0",
|
|
26
|
-
"express": "^4.18.2",
|
|
27
47
|
"ts-morph": "^21.0.1",
|
|
28
|
-
"
|
|
48
|
+
"zod": "^4.2.0"
|
|
29
49
|
},
|
|
30
50
|
"devDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"react": "^19.0.0",
|
|
35
|
-
"react-dom": "^19.0.0",
|
|
36
|
-
"tailwindcss": "^4.1.17",
|
|
37
|
-
"tw-animate-css": "^1.4.0",
|
|
51
|
+
"@types/node": "^25.0.2",
|
|
52
|
+
"tsup": "^8.5.1",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
38
54
|
"vite": "^7.1.7"
|
|
39
|
-
},
|
|
40
|
-
"peerDependencies": {
|
|
41
|
-
"react": "^19.0.0",
|
|
42
|
-
"react-dom": "^19.0.0"
|
|
43
55
|
}
|
|
44
56
|
}
|
package/bin/rayburst.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import { spawn } from 'child_process';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import { dirname, join, resolve } from 'path';
|
|
8
|
-
import {
|
|
9
|
-
registerProject,
|
|
10
|
-
unregisterProject,
|
|
11
|
-
listProjects,
|
|
12
|
-
getRegistryPaths,
|
|
13
|
-
writeAnalysisData,
|
|
14
|
-
updateProjectAnalysis,
|
|
15
|
-
} from '../src/registry.js';
|
|
16
|
-
import { analyzeProject } from '../scripts/analyze-project.js';
|
|
17
|
-
|
|
18
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
-
const __dirname = dirname(__filename);
|
|
20
|
-
|
|
21
|
-
const program = new Command();
|
|
22
|
-
|
|
23
|
-
program
|
|
24
|
-
.name('rayburst')
|
|
25
|
-
.description('Rayburst CLI - Module Federation Host')
|
|
26
|
-
.version('0.1.0');
|
|
27
|
-
|
|
28
|
-
program
|
|
29
|
-
.command('start')
|
|
30
|
-
.description('Start the Rayburst application')
|
|
31
|
-
.option('-p, --port <port>', 'Port to run the server on', '3105')
|
|
32
|
-
.option('-e, --env <environment>', 'Environment (development|staging|production)', 'development')
|
|
33
|
-
.action((options) => {
|
|
34
|
-
console.log(chalk.blue('🚀 Starting Rayburst CLI...'));
|
|
35
|
-
console.log(chalk.gray(` Port: ${options.port}`));
|
|
36
|
-
console.log(chalk.gray(` Environment: ${options.env}`));
|
|
37
|
-
|
|
38
|
-
const serverPath = join(__dirname, '..', 'server.js');
|
|
39
|
-
|
|
40
|
-
const env = {
|
|
41
|
-
...process.env,
|
|
42
|
-
PORT: options.port,
|
|
43
|
-
NODE_ENV: options.env,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const server = spawn('node', [serverPath], {
|
|
47
|
-
env,
|
|
48
|
-
stdio: 'inherit',
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
server.on('error', (err) => {
|
|
52
|
-
console.error(chalk.red('Failed to start server:'), err);
|
|
53
|
-
process.exit(1);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
server.on('exit', (code) => {
|
|
57
|
-
if (code !== 0) {
|
|
58
|
-
console.error(chalk.red(`Server exited with code ${code}`));
|
|
59
|
-
process.exit(code);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
process.on('SIGINT', () => {
|
|
64
|
-
console.log(chalk.yellow('\n👋 Shutting down Rayburst CLI...'));
|
|
65
|
-
server.kill('SIGINT');
|
|
66
|
-
process.exit(0);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
program
|
|
71
|
-
.command('register')
|
|
72
|
-
.description('Register the current directory as a Rayburst project')
|
|
73
|
-
.argument('[path]', 'Path to register (defaults to current directory)', '.')
|
|
74
|
-
.option('--no-analyze', 'Skip automatic code analysis')
|
|
75
|
-
.action((projectPath, options) => {
|
|
76
|
-
try {
|
|
77
|
-
console.log(chalk.blue('📦 Registering project...'));
|
|
78
|
-
const project = registerProject(projectPath);
|
|
79
|
-
console.log(chalk.green('✓ Project registered successfully!'));
|
|
80
|
-
console.log(chalk.gray(` Name: ${project.name}`));
|
|
81
|
-
console.log(chalk.gray(` Path: ${project.path}`));
|
|
82
|
-
console.log(chalk.gray(` ID: ${project.id}`));
|
|
83
|
-
console.log();
|
|
84
|
-
|
|
85
|
-
// Run analysis by default
|
|
86
|
-
if (options.analyze !== false) {
|
|
87
|
-
console.log(chalk.blue('🔍 Analyzing project...'));
|
|
88
|
-
try {
|
|
89
|
-
const analysisData = analyzeProject(project.path);
|
|
90
|
-
writeAnalysisData(project.id, analysisData);
|
|
91
|
-
updateProjectAnalysis(project.id);
|
|
92
|
-
console.log(chalk.green('✓ Analysis complete!'));
|
|
93
|
-
console.log(chalk.gray(` Nodes: ${analysisData.planData[Object.keys(analysisData.planData)[0]]?.nodes?.length || 0}`));
|
|
94
|
-
console.log(chalk.gray(` Edges: ${analysisData.planData[Object.keys(analysisData.planData)[0]]?.edges?.length || 0}`));
|
|
95
|
-
} catch (error) {
|
|
96
|
-
console.warn(chalk.yellow('⚠ Analysis failed:'), error.message);
|
|
97
|
-
console.warn(chalk.dim(' Project registered but without analysis data'));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
console.log();
|
|
102
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst list'), chalk.dim('to see all registered projects'));
|
|
103
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst start'), chalk.dim('to open the Rayburst dashboard'));
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(chalk.red('✗ Registration failed:'), error.message);
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
program
|
|
111
|
-
.command('unregister')
|
|
112
|
-
.description('Unregister a Rayburst project')
|
|
113
|
-
.argument('[path]', 'Path or project ID to unregister (defaults to current directory)', '.')
|
|
114
|
-
.action((projectPath) => {
|
|
115
|
-
try {
|
|
116
|
-
console.log(chalk.blue('📦 Unregistering project...'));
|
|
117
|
-
const project = unregisterProject(projectPath);
|
|
118
|
-
console.log(chalk.green('✓ Project unregistered successfully!'));
|
|
119
|
-
console.log(chalk.gray(` Name: ${project.name}`));
|
|
120
|
-
console.log(chalk.gray(` Path: ${project.path}`));
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error(chalk.red('✗ Unregistration failed:'), error.message);
|
|
123
|
-
process.exit(1);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
program
|
|
128
|
-
.command('list')
|
|
129
|
-
.description('List all registered Rayburst projects')
|
|
130
|
-
.action(() => {
|
|
131
|
-
try {
|
|
132
|
-
const projects = listProjects();
|
|
133
|
-
|
|
134
|
-
if (projects.length === 0) {
|
|
135
|
-
console.log(chalk.yellow('No projects registered yet.'));
|
|
136
|
-
console.log();
|
|
137
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst register'), chalk.dim('in a project directory to register it'));
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
console.log(chalk.blue(`📦 Registered Projects (${projects.length}):\n`));
|
|
142
|
-
|
|
143
|
-
projects.forEach((project, index) => {
|
|
144
|
-
console.log(chalk.bold(`${index + 1}. ${project.name}`));
|
|
145
|
-
console.log(chalk.gray(` Path: ${project.path}`));
|
|
146
|
-
console.log(chalk.gray(` ID: ${project.id}`));
|
|
147
|
-
console.log(chalk.gray(` Version: ${project.packageJson?.version || 'N/A'}`));
|
|
148
|
-
console.log(chalk.gray(` Registered: ${new Date(project.registeredAt).toLocaleString()}`));
|
|
149
|
-
if (project.lastAnalyzed) {
|
|
150
|
-
console.log(chalk.gray(` Last Analyzed: ${new Date(project.lastAnalyzed).toLocaleString()}`));
|
|
151
|
-
}
|
|
152
|
-
console.log();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const paths = getRegistryPaths();
|
|
156
|
-
console.log(chalk.dim(`Registry location: ${paths.projectsFile}`));
|
|
157
|
-
} catch (error) {
|
|
158
|
-
console.error(chalk.red('✗ Failed to list projects:'), error.message);
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
program
|
|
164
|
-
.command('analyze')
|
|
165
|
-
.description('Analyze a registered Rayburst project')
|
|
166
|
-
.argument('[path]', 'Path or project ID to analyze (defaults to current directory)', '.')
|
|
167
|
-
.action((projectPath) => {
|
|
168
|
-
try {
|
|
169
|
-
// Find the project by path or ID
|
|
170
|
-
const projects = listProjects();
|
|
171
|
-
const absolutePath = resolve(projectPath);
|
|
172
|
-
|
|
173
|
-
let project = projects.find(p => p.path === absolutePath);
|
|
174
|
-
if (!project) {
|
|
175
|
-
// Try to find by ID
|
|
176
|
-
project = projects.find(p => p.id === projectPath);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (!project) {
|
|
180
|
-
console.error(chalk.red('✗ Project not found. Make sure it\'s registered first.'));
|
|
181
|
-
console.log();
|
|
182
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst list'), chalk.dim('to see registered projects'));
|
|
183
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst register'), chalk.dim('to register a new project'));
|
|
184
|
-
process.exit(1);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
console.log(chalk.blue('🔍 Analyzing project...'));
|
|
188
|
-
console.log(chalk.gray(` Name: ${project.name}`));
|
|
189
|
-
console.log(chalk.gray(` Path: ${project.path}`));
|
|
190
|
-
console.log();
|
|
191
|
-
|
|
192
|
-
const analysisData = analyzeProject(project.path);
|
|
193
|
-
writeAnalysisData(project.id, analysisData);
|
|
194
|
-
updateProjectAnalysis(project.id);
|
|
195
|
-
|
|
196
|
-
console.log(chalk.green('✓ Analysis complete!'));
|
|
197
|
-
|
|
198
|
-
// Show stats for each branch
|
|
199
|
-
const branchIds = Object.keys(analysisData.planData);
|
|
200
|
-
console.log(chalk.gray(` Branches analyzed: ${branchIds.length}`));
|
|
201
|
-
|
|
202
|
-
branchIds.forEach(branchId => {
|
|
203
|
-
const planData = analysisData.planData[branchId];
|
|
204
|
-
const branch = analysisData.branches.find(b => b.id === branchId);
|
|
205
|
-
console.log(chalk.gray(` - ${branch?.name || branchId}: ${planData.nodes.length} nodes, ${planData.edges.length} edges`));
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
console.log();
|
|
209
|
-
console.log(chalk.dim('💡 Run'), chalk.cyan('rayburst start'), chalk.dim('to view the analysis in the dashboard'));
|
|
210
|
-
} catch (error) {
|
|
211
|
-
console.error(chalk.red('✗ Analysis failed:'), error.message);
|
|
212
|
-
process.exit(1);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
program.parse();
|
package/index.html
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Rayburst</title>
|
|
7
|
-
<style>
|
|
8
|
-
/* Scoped styles for loading screen only - do not interfere with remote app styles */
|
|
9
|
-
.loading-container {
|
|
10
|
-
display: flex;
|
|
11
|
-
flex-direction: column;
|
|
12
|
-
align-items: center;
|
|
13
|
-
justify-content: center;
|
|
14
|
-
height: 100vh;
|
|
15
|
-
width: 100%;
|
|
16
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
-
color: white;
|
|
18
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
19
|
-
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
20
|
-
sans-serif;
|
|
21
|
-
-webkit-font-smoothing: antialiased;
|
|
22
|
-
-moz-osx-font-smoothing: grayscale;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.spinner {
|
|
26
|
-
width: 50px;
|
|
27
|
-
height: 50px;
|
|
28
|
-
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
29
|
-
border-top-color: white;
|
|
30
|
-
border-radius: 50%;
|
|
31
|
-
animation: spin 1s linear infinite;
|
|
32
|
-
margin-bottom: 20px;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@keyframes spin {
|
|
36
|
-
to { transform: rotate(360deg); }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.loading-text {
|
|
40
|
-
font-size: 18px;
|
|
41
|
-
font-weight: 500;
|
|
42
|
-
}
|
|
43
|
-
</style>
|
|
44
|
-
</head>
|
|
45
|
-
<body>
|
|
46
|
-
<div id="app">
|
|
47
|
-
<div class="loading-container">
|
|
48
|
-
<div class="spinner"></div>
|
|
49
|
-
<div class="loading-text">Loading Rayburst...</div>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
53
|
-
</body>
|
|
54
|
-
</html>
|