create-aziz-app 2.0.8 → 2.0.10
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/bin/create-aziz-app.js +15 -8
- package/package.json +1 -1
- package/template/README.md +1 -0
- package/template/app.html +3 -0
- package/template/docs/TROUBLESHOOTING.md +282 -0
- package/template/scripts/dev-server.js +80 -58
package/bin/create-aziz-app.js
CHANGED
|
@@ -197,6 +197,17 @@ function setupCSSFramework(targetDir, framework) {
|
|
|
197
197
|
|
|
198
198
|
let html = fs.readFileSync(htmlPath, 'utf8');
|
|
199
199
|
|
|
200
|
+
// Ensure cache-control meta tags are present
|
|
201
|
+
if (!html.includes('http-equiv="Cache-Control"')) {
|
|
202
|
+
html = html.replace(
|
|
203
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1.0">',
|
|
204
|
+
`<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
205
|
+
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
|
206
|
+
<meta http-equiv="Pragma" content="no-cache">
|
|
207
|
+
<meta http-equiv="Expires" content="0">`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
200
211
|
if (framework === 'bootstrap') {
|
|
201
212
|
// Replace globals.css with Bootstrap CDN
|
|
202
213
|
html = html.replace(
|
|
@@ -430,8 +441,7 @@ function updatePagesForTailwind(targetDir) {
|
|
|
430
441
|
function getBootstrapHomePage() {
|
|
431
442
|
return `/** @jsx h */
|
|
432
443
|
|
|
433
|
-
|
|
434
|
-
|
|
444
|
+
// Auto-registered as "home" route
|
|
435
445
|
function HomePage() {
|
|
436
446
|
return (
|
|
437
447
|
<div class="container py-5">
|
|
@@ -481,8 +491,7 @@ function HomePage() {
|
|
|
481
491
|
function getTailwindHomePage() {
|
|
482
492
|
return `/** @jsx h */
|
|
483
493
|
|
|
484
|
-
|
|
485
|
-
|
|
494
|
+
// Auto-registered as "home" route
|
|
486
495
|
function HomePage() {
|
|
487
496
|
return (
|
|
488
497
|
<div class="container mx-auto py-10 px-4">
|
|
@@ -528,8 +537,7 @@ function HomePage() {
|
|
|
528
537
|
function getBootstrapTestPage() {
|
|
529
538
|
return `/** @jsx h */
|
|
530
539
|
|
|
531
|
-
|
|
532
|
-
|
|
540
|
+
// Auto-registered as "test" route
|
|
533
541
|
function TestPage() {
|
|
534
542
|
const [count, setCount] = useState(0);
|
|
535
543
|
const [name, setName] = useState('');
|
|
@@ -616,8 +624,7 @@ function TestPage() {
|
|
|
616
624
|
function getTailwindTestPage() {
|
|
617
625
|
return `/** @jsx h */
|
|
618
626
|
|
|
619
|
-
|
|
620
|
-
|
|
627
|
+
// Auto-registered as "test" route
|
|
621
628
|
function TestPage() {
|
|
622
629
|
const [count, setCount] = useState(0);
|
|
623
630
|
const [name, setName] = useState('');
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -155,6 +155,7 @@ The CLI will automatically set up your chosen framework!
|
|
|
155
155
|
- **[API Guide](docs/API-GUIDE.md)** - How to create API routes
|
|
156
156
|
- **[Auto-Import](docs/AUTO-IMPORT.md)** - Auto-import system details
|
|
157
157
|
- **[Dev Server](docs/DEV-SERVER.md)** - Live reload and development
|
|
158
|
+
- **[Troubleshooting](docs/TROUBLESHOOTING.md)** - Fix common issues
|
|
158
159
|
- **[Quick Start](docs/QUICK-START.md)** - Quick examples
|
|
159
160
|
|
|
160
161
|
## 🛠️ Commands
|
package/template/app.html
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
|
7
|
+
<meta http-equiv="Pragma" content="no-cache">
|
|
8
|
+
<meta http-equiv="Expires" content="0">
|
|
6
9
|
<title>My Aziz App</title>
|
|
7
10
|
|
|
8
11
|
<!-- Global Styles -->
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
## Live Reload Issues
|
|
4
|
+
|
|
5
|
+
### Indicator Stuck on "Connecting..."
|
|
6
|
+
|
|
7
|
+
**Symptoms:**
|
|
8
|
+
- Green indicator shows "🔌 Connecting..." and never changes
|
|
9
|
+
- Changes don't show without hard refresh (Ctrl+Shift+R)
|
|
10
|
+
|
|
11
|
+
**Causes:**
|
|
12
|
+
- Browser cached old version of `app.html` without live reload script
|
|
13
|
+
- SSE connection blocked by browser extension or firewall
|
|
14
|
+
|
|
15
|
+
**Solutions:**
|
|
16
|
+
|
|
17
|
+
1. **Hard refresh once** to clear cache:
|
|
18
|
+
- Windows/Linux: `Ctrl + Shift + R`
|
|
19
|
+
- Mac: `Cmd + Shift + R`
|
|
20
|
+
|
|
21
|
+
2. **Check browser console** (F12):
|
|
22
|
+
- Look for: `"🔌 Connecting to live reload at http://localhost:3000/live-reload"`
|
|
23
|
+
- Look for: `"✅ Live reload connected"`
|
|
24
|
+
- If you see errors, note them
|
|
25
|
+
|
|
26
|
+
3. **Disable browser extensions** temporarily:
|
|
27
|
+
- Ad blockers can block SSE connections
|
|
28
|
+
- Try in incognito/private mode
|
|
29
|
+
|
|
30
|
+
4. **Check terminal output**:
|
|
31
|
+
- Should show: `"🔌 [time] Browser connected for live reload (1 total)"`
|
|
32
|
+
- If not showing, SSE connection failed
|
|
33
|
+
|
|
34
|
+
5. **Restart dev server**:
|
|
35
|
+
```bash
|
|
36
|
+
# Stop with Ctrl+C
|
|
37
|
+
npm run dev
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
6. **Clear browser cache completely**:
|
|
41
|
+
- Chrome: Settings → Privacy → Clear browsing data
|
|
42
|
+
- Firefox: Settings → Privacy → Clear Data
|
|
43
|
+
- Edge: Settings → Privacy → Clear browsing data
|
|
44
|
+
|
|
45
|
+
### Changes Not Showing
|
|
46
|
+
|
|
47
|
+
**Symptoms:**
|
|
48
|
+
- Indicator shows "✅ Live Reload Active"
|
|
49
|
+
- Page reloads but changes don't appear
|
|
50
|
+
|
|
51
|
+
**Solutions:**
|
|
52
|
+
|
|
53
|
+
1. **Check file was saved**:
|
|
54
|
+
- Verify file has no unsaved indicator in editor
|
|
55
|
+
- Check terminal shows: `"📝 Detected change: pages/Home.jsx"`
|
|
56
|
+
|
|
57
|
+
2. **Check imports were regenerated**:
|
|
58
|
+
- Terminal should show: `"🔄 Regenerating imports..."`
|
|
59
|
+
- Check `app.html` has your file listed
|
|
60
|
+
|
|
61
|
+
3. **Verify file location**:
|
|
62
|
+
- Files must be in: `api/`, `components/`, `pages/`, `modules/`, or `styles/`
|
|
63
|
+
- Files outside these folders won't trigger reload
|
|
64
|
+
|
|
65
|
+
4. **Check for JavaScript errors**:
|
|
66
|
+
- Open browser console (F12)
|
|
67
|
+
- Look for red error messages
|
|
68
|
+
- Fix any syntax errors in your code
|
|
69
|
+
|
|
70
|
+
5. **Manual import regeneration**:
|
|
71
|
+
```bash
|
|
72
|
+
npm run build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Indicator Shows "❌ Connection Error"
|
|
76
|
+
|
|
77
|
+
**Symptoms:**
|
|
78
|
+
- Red indicator with error message
|
|
79
|
+
- Console shows EventSource errors
|
|
80
|
+
|
|
81
|
+
**Solutions:**
|
|
82
|
+
|
|
83
|
+
1. **Check dev server is running**:
|
|
84
|
+
- Terminal should show: `"✅ Dev server running with live reload!"`
|
|
85
|
+
- If not, run: `npm run dev`
|
|
86
|
+
|
|
87
|
+
2. **Check port is correct**:
|
|
88
|
+
- Browser URL should match terminal output
|
|
89
|
+
- Example: `http://localhost:3000/`
|
|
90
|
+
|
|
91
|
+
3. **Firewall blocking connection**:
|
|
92
|
+
- Allow Node.js through firewall
|
|
93
|
+
- Try different port: `PORT=3001 npm run dev`
|
|
94
|
+
|
|
95
|
+
4. **Browser doesn't support EventSource**:
|
|
96
|
+
- Update to latest browser version
|
|
97
|
+
- Try different browser (Chrome, Firefox, Edge)
|
|
98
|
+
|
|
99
|
+
## Page Not Found (404)
|
|
100
|
+
|
|
101
|
+
**Symptoms:**
|
|
102
|
+
- Clicking link shows 404 page
|
|
103
|
+
- URL is correct but page doesn't load
|
|
104
|
+
|
|
105
|
+
**Solutions:**
|
|
106
|
+
|
|
107
|
+
1. **Check function name**:
|
|
108
|
+
```jsx
|
|
109
|
+
// ✅ Correct - ends with "Page"
|
|
110
|
+
function AboutPage() { }
|
|
111
|
+
|
|
112
|
+
// ❌ Wrong - missing "Page"
|
|
113
|
+
function About() { }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
2. **Check file is loaded**:
|
|
117
|
+
- Open `app.html`
|
|
118
|
+
- Look for: `<script type="text/babel" src="pages/YourPage.jsx"></script>`
|
|
119
|
+
- If missing, run: `npm run build`
|
|
120
|
+
|
|
121
|
+
3. **Check browser console**:
|
|
122
|
+
- Look for: `"📄 Auto-registered: about → AboutPage()"`
|
|
123
|
+
- If missing, function name is wrong
|
|
124
|
+
|
|
125
|
+
4. **Manual registration**:
|
|
126
|
+
```jsx
|
|
127
|
+
// Add this if auto-registration fails
|
|
128
|
+
registerPage("about", AboutPage);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## State Not Working
|
|
132
|
+
|
|
133
|
+
**Symptoms:**
|
|
134
|
+
- `useState` is undefined
|
|
135
|
+
- State doesn't update
|
|
136
|
+
|
|
137
|
+
**Solutions:**
|
|
138
|
+
|
|
139
|
+
1. **Check `/** @jsx h */` at top of file**:
|
|
140
|
+
```jsx
|
|
141
|
+
/** @jsx h */
|
|
142
|
+
|
|
143
|
+
function MyPage() {
|
|
144
|
+
const [count, setCount] = useState(0);
|
|
145
|
+
// ...
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
2. **Check state.js is loaded**:
|
|
150
|
+
- Open `app.html`
|
|
151
|
+
- Look for: `<script type="text/babel" src="modules/state.js"></script>`
|
|
152
|
+
|
|
153
|
+
3. **Check browser console for errors**:
|
|
154
|
+
- Look for: `"useState is not defined"`
|
|
155
|
+
- If found, state.js didn't load
|
|
156
|
+
|
|
157
|
+
## Styling Not Applied
|
|
158
|
+
|
|
159
|
+
**Symptoms:**
|
|
160
|
+
- Page has no styling
|
|
161
|
+
- Looks like plain HTML
|
|
162
|
+
|
|
163
|
+
**Solutions:**
|
|
164
|
+
|
|
165
|
+
1. **Check CSS file is linked**:
|
|
166
|
+
- Open `app.html`
|
|
167
|
+
- Look for: `<link rel="stylesheet" href="styles/globals.css">`
|
|
168
|
+
|
|
169
|
+
2. **Check CSS file exists**:
|
|
170
|
+
- Verify `styles/globals.css` exists
|
|
171
|
+
- Check file has content
|
|
172
|
+
|
|
173
|
+
3. **Check class names**:
|
|
174
|
+
```jsx
|
|
175
|
+
// ✅ Correct
|
|
176
|
+
<div class="card">
|
|
177
|
+
|
|
178
|
+
// ❌ Wrong (React syntax)
|
|
179
|
+
<div className="card">
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
4. **Hard refresh**:
|
|
183
|
+
- CSS might be cached
|
|
184
|
+
- Press: `Ctrl + Shift + R` (Windows) or `Cmd + Shift + R` (Mac)
|
|
185
|
+
|
|
186
|
+
## API Routes Not Working
|
|
187
|
+
|
|
188
|
+
**Symptoms:**
|
|
189
|
+
- `fetchApi()` returns 404
|
|
190
|
+
- API endpoint not found
|
|
191
|
+
|
|
192
|
+
**Solutions:**
|
|
193
|
+
|
|
194
|
+
1. **Check API file is loaded**:
|
|
195
|
+
- Open `app.html`
|
|
196
|
+
- Look for: `<script type="text/babel" src="api/yourfile.js"></script>`
|
|
197
|
+
|
|
198
|
+
2. **Check route registration**:
|
|
199
|
+
```jsx
|
|
200
|
+
// In api/users.js
|
|
201
|
+
registerApiRoute('users', async (req, res) => {
|
|
202
|
+
// handler
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
3. **Check URL format**:
|
|
207
|
+
```jsx
|
|
208
|
+
// ✅ Correct
|
|
209
|
+
await fetchApi('/api/users');
|
|
210
|
+
|
|
211
|
+
// ❌ Wrong
|
|
212
|
+
await fetchApi('api/users'); // missing leading /
|
|
213
|
+
await fetchApi('/users'); // missing /api/
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
4. **Check browser console**:
|
|
217
|
+
- Look for network errors
|
|
218
|
+
- Check request URL is correct
|
|
219
|
+
|
|
220
|
+
## Port Already in Use
|
|
221
|
+
|
|
222
|
+
**Symptoms:**
|
|
223
|
+
- Error: `EADDRINUSE: address already in use :::3000`
|
|
224
|
+
|
|
225
|
+
**Solutions:**
|
|
226
|
+
|
|
227
|
+
1. **Server auto-finds next port**:
|
|
228
|
+
- Check terminal for actual port
|
|
229
|
+
- Example: `"Server running at http://localhost:3001/"`
|
|
230
|
+
|
|
231
|
+
2. **Kill process on port 3000**:
|
|
232
|
+
```bash
|
|
233
|
+
# Windows
|
|
234
|
+
netstat -ano | findstr :3000
|
|
235
|
+
taskkill /PID <PID> /F
|
|
236
|
+
|
|
237
|
+
# Mac/Linux
|
|
238
|
+
lsof -ti:3000 | xargs kill -9
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
3. **Use different port**:
|
|
242
|
+
```bash
|
|
243
|
+
PORT=3001 npm run dev
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## General Tips
|
|
247
|
+
|
|
248
|
+
### Before Asking for Help
|
|
249
|
+
|
|
250
|
+
1. **Check browser console** (F12) for errors
|
|
251
|
+
2. **Check terminal output** for server errors
|
|
252
|
+
3. **Try hard refresh** (Ctrl+Shift+R)
|
|
253
|
+
4. **Try incognito mode** to rule out extensions
|
|
254
|
+
5. **Restart dev server** (Ctrl+C, then `npm run dev`)
|
|
255
|
+
|
|
256
|
+
### Debug Checklist
|
|
257
|
+
|
|
258
|
+
- [ ] Dev server is running
|
|
259
|
+
- [ ] Browser URL matches server URL
|
|
260
|
+
- [ ] File is saved
|
|
261
|
+
- [ ] File is in correct folder
|
|
262
|
+
- [ ] `/** @jsx h */` at top of JSX files
|
|
263
|
+
- [ ] Function name ends with "Page"
|
|
264
|
+
- [ ] No JavaScript errors in console
|
|
265
|
+
- [ ] Live reload indicator is green
|
|
266
|
+
|
|
267
|
+
### Still Having Issues?
|
|
268
|
+
|
|
269
|
+
1. **Check documentation**:
|
|
270
|
+
- [Getting Started](GETTING-STARTED.md)
|
|
271
|
+
- [Auto-Registration](AUTO-REGISTRATION.md)
|
|
272
|
+
- [Dev Server](DEV-SERVER.md)
|
|
273
|
+
|
|
274
|
+
2. **Create minimal reproduction**:
|
|
275
|
+
- Create new app: `npx create-aziz-app test-app`
|
|
276
|
+
- Test if issue persists in fresh app
|
|
277
|
+
|
|
278
|
+
3. **Report issue** with:
|
|
279
|
+
- Browser console output
|
|
280
|
+
- Terminal output
|
|
281
|
+
- Code that's not working
|
|
282
|
+
- Steps to reproduce
|
|
@@ -34,106 +34,128 @@ function notifyClients() {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Live reload script to inject
|
|
37
|
-
|
|
37
|
+
function getLiveReloadScript() {
|
|
38
|
+
return `
|
|
38
39
|
<script>
|
|
39
40
|
(function() {
|
|
40
41
|
// Create visual indicator
|
|
41
42
|
const indicator = document.createElement('div');
|
|
42
43
|
indicator.id = 'live-reload-indicator';
|
|
43
|
-
indicator.style.cssText =
|
|
44
|
-
position: fixed;
|
|
45
|
-
bottom: 20px;
|
|
46
|
-
right: 20px;
|
|
47
|
-
background: #4caf50;
|
|
48
|
-
color: white;
|
|
49
|
-
padding: 8px 16px;
|
|
50
|
-
border-radius: 20px;
|
|
51
|
-
font-size: 12px;
|
|
52
|
-
font-family: monospace;
|
|
53
|
-
z-index: 9999;
|
|
54
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
|
55
|
-
transition: all 0.3s;
|
|
56
|
-
\`;
|
|
44
|
+
indicator.style.cssText = 'position: fixed; bottom: 20px; right: 20px; background: #4caf50; color: white; padding: 8px 16px; border-radius: 20px; font-size: 12px; font-family: monospace; z-index: 9999; box-shadow: 0 2px 8px rgba(0,0,0,0.2); transition: all 0.3s;';
|
|
57
45
|
indicator.textContent = '🔌 Connecting...';
|
|
58
46
|
document.body.appendChild(indicator);
|
|
59
47
|
|
|
60
48
|
// Live reload client
|
|
61
|
-
console.log('🔌 Connecting to live reload
|
|
62
|
-
const evtSource = new EventSource('/live-reload');
|
|
49
|
+
console.log('🔌 Connecting to live reload at ' + window.location.origin + '/live-reload');
|
|
63
50
|
|
|
64
|
-
evtSource
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
indicator.textContent = '✅ Live Reload Active';
|
|
68
|
-
// Hide after 2 seconds
|
|
69
|
-
setTimeout(() => {
|
|
70
|
-
indicator.style.opacity = '0.3';
|
|
71
|
-
}, 2000);
|
|
72
|
-
};
|
|
51
|
+
let evtSource;
|
|
52
|
+
let reconnectAttempts = 0;
|
|
53
|
+
const maxReconnectAttempts = 5;
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
55
|
+
function connect() {
|
|
56
|
+
try {
|
|
57
|
+
evtSource = new EventSource('/live-reload');
|
|
58
|
+
|
|
59
|
+
evtSource.onopen = function() {
|
|
60
|
+
console.log('✅ Live reload connected');
|
|
61
|
+
reconnectAttempts = 0;
|
|
62
|
+
indicator.style.background = '#4caf50';
|
|
63
|
+
indicator.textContent = '✅ Live Reload Active';
|
|
64
|
+
setTimeout(function() {
|
|
65
|
+
indicator.style.opacity = '0.3';
|
|
66
|
+
}, 2000);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
evtSource.onmessage = function(event) {
|
|
70
|
+
if (event.data === 'reload') {
|
|
71
|
+
console.log('🔄 Changes detected, reloading...');
|
|
72
|
+
indicator.style.opacity = '1';
|
|
73
|
+
indicator.style.background = '#2196f3';
|
|
74
|
+
indicator.textContent = '🔄 Reloading...';
|
|
75
|
+
setTimeout(function() {
|
|
76
|
+
// Add timestamp to force cache bust
|
|
77
|
+
var url = window.location.href.split('?')[0];
|
|
78
|
+
window.location.href = url + '?t=' + Date.now();
|
|
79
|
+
}, 100);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
evtSource.onerror = function(err) {
|
|
84
|
+
console.log('⚠️ Live reload connection error');
|
|
85
|
+
indicator.style.background = '#ff9800';
|
|
86
|
+
indicator.style.opacity = '1';
|
|
87
|
+
indicator.textContent = '⚠️ Connection Lost';
|
|
88
|
+
|
|
89
|
+
if (evtSource) {
|
|
90
|
+
evtSource.close();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (reconnectAttempts < maxReconnectAttempts) {
|
|
94
|
+
reconnectAttempts++;
|
|
95
|
+
console.log('Reconnecting... attempt ' + reconnectAttempts);
|
|
96
|
+
setTimeout(connect, 2000);
|
|
97
|
+
} else {
|
|
98
|
+
indicator.textContent = '❌ Reload Failed';
|
|
99
|
+
console.log('Max reconnection attempts reached. Please refresh manually.');
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error('Failed to create EventSource:', e);
|
|
104
|
+
indicator.style.background = '#f44336';
|
|
105
|
+
indicator.textContent = '❌ Connection Error';
|
|
84
106
|
}
|
|
85
|
-
}
|
|
107
|
+
}
|
|
86
108
|
|
|
87
|
-
|
|
88
|
-
console.log('⚠️ Live reload disconnected, retrying...');
|
|
89
|
-
indicator.style.background = '#ff9800';
|
|
90
|
-
indicator.style.opacity = '1';
|
|
91
|
-
indicator.textContent = '⚠️ Reconnecting...';
|
|
92
|
-
evtSource.close();
|
|
93
|
-
// Retry connection after 2 seconds
|
|
94
|
-
setTimeout(() => {
|
|
95
|
-
window.location.reload();
|
|
96
|
-
}, 2000);
|
|
97
|
-
};
|
|
109
|
+
connect();
|
|
98
110
|
|
|
99
111
|
// Show indicator on hover
|
|
100
|
-
indicator.addEventListener('mouseenter', ()
|
|
112
|
+
indicator.addEventListener('mouseenter', function() {
|
|
101
113
|
indicator.style.opacity = '1';
|
|
102
114
|
});
|
|
103
|
-
indicator.addEventListener('mouseleave', ()
|
|
104
|
-
indicator.
|
|
115
|
+
indicator.addEventListener('mouseleave', function() {
|
|
116
|
+
if (indicator.textContent.includes('Active')) {
|
|
117
|
+
indicator.style.opacity = '0.3';
|
|
118
|
+
}
|
|
105
119
|
});
|
|
106
120
|
})();
|
|
107
121
|
</script>
|
|
108
122
|
`;
|
|
123
|
+
}
|
|
109
124
|
|
|
110
125
|
// Create HTTP server
|
|
111
126
|
function createServer(port) {
|
|
112
127
|
return http.createServer((req, res) => {
|
|
113
128
|
// Handle live reload SSE endpoint
|
|
114
|
-
if (req.url === '/live-reload') {
|
|
129
|
+
if (req.url === '/live-reload' || req.url.startsWith('/live-reload?')) {
|
|
115
130
|
res.writeHead(200, {
|
|
116
131
|
'Content-Type': 'text/event-stream',
|
|
117
|
-
'Cache-Control': 'no-cache',
|
|
132
|
+
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
118
133
|
'Connection': 'keep-alive',
|
|
119
|
-
'Access-Control-Allow-Origin': '*'
|
|
134
|
+
'Access-Control-Allow-Origin': '*',
|
|
135
|
+
'X-Accel-Buffering': 'no'
|
|
120
136
|
});
|
|
121
137
|
|
|
138
|
+
// Send initial connection message
|
|
139
|
+
res.write(':ok\n\n');
|
|
140
|
+
|
|
122
141
|
clients.push(res);
|
|
123
|
-
|
|
142
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
143
|
+
console.log(`🔌 [${timestamp}] Browser connected for live reload (${clients.length} total)`);
|
|
124
144
|
|
|
125
145
|
req.on('close', () => {
|
|
126
146
|
const index = clients.indexOf(res);
|
|
127
147
|
if (index !== -1) {
|
|
128
148
|
clients.splice(index, 1);
|
|
129
149
|
}
|
|
130
|
-
|
|
150
|
+
const closeTime = new Date().toLocaleTimeString();
|
|
151
|
+
console.log(`🔌 [${closeTime}] Browser disconnected (${clients.length} remaining)`);
|
|
131
152
|
});
|
|
132
153
|
|
|
133
154
|
return;
|
|
134
155
|
}
|
|
135
156
|
|
|
136
|
-
|
|
157
|
+
// Strip query parameters for file serving (cache busting)
|
|
158
|
+
let filePath = '.' + req.url.split('?')[0];
|
|
137
159
|
if (filePath === './') {
|
|
138
160
|
filePath = './app.html';
|
|
139
161
|
}
|
|
@@ -172,7 +194,7 @@ function createServer(port) {
|
|
|
172
194
|
} else {
|
|
173
195
|
// Inject live reload script into HTML files
|
|
174
196
|
if (extname === '.html') {
|
|
175
|
-
content = content.toString().replace('</body>',
|
|
197
|
+
content = content.toString().replace('</body>', getLiveReloadScript() + '</body>');
|
|
176
198
|
}
|
|
177
199
|
|
|
178
200
|
// Add cache control headers to prevent caching during development
|