elit 3.4.0 → 3.4.2
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/dist/cli.js +53864 -315
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +3 -0
- package/dist/hmr.js.map +1 -1
- package/dist/hmr.mjs +3 -0
- package/dist/hmr.mjs.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53697 -142
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +53716 -151
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -1
- package/src/hmr.ts +5 -0
- package/src/server.ts +145 -103
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elit",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.2",
|
|
4
4
|
"description": "Optimized lightweight library for creating DOM elements with reactive state",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
"homepage": "https://d-osc.github.io/elit/",
|
|
184
184
|
"dependencies": {
|
|
185
185
|
"esbuild": "^0.27.3",
|
|
186
|
+
"esbuild-obfuscator-plugin": "^0.0.5",
|
|
186
187
|
"open": "^11.0.0",
|
|
187
188
|
"source-map": "^0.7.6"
|
|
188
189
|
},
|
package/src/hmr.ts
CHANGED
package/src/server.ts
CHANGED
|
@@ -877,6 +877,8 @@ export function security(): Middleware {
|
|
|
877
877
|
ctx.res.setHeader('X-Frame-Options', 'DENY');
|
|
878
878
|
ctx.res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
879
879
|
ctx.res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
|
880
|
+
ctx.res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
881
|
+
ctx.res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
|
|
880
882
|
await next();
|
|
881
883
|
};
|
|
882
884
|
}
|
|
@@ -1534,8 +1536,8 @@ export default css;
|
|
|
1534
1536
|
const result = await Deno.emit(resolvedPath, {
|
|
1535
1537
|
check: false,
|
|
1536
1538
|
compilerOptions: {
|
|
1537
|
-
sourceMap:
|
|
1538
|
-
inlineSourceMap:
|
|
1539
|
+
sourceMap: config.mode !== 'preview',
|
|
1540
|
+
inlineSourceMap: config.mode !== 'preview',
|
|
1539
1541
|
target: 'ES2020',
|
|
1540
1542
|
module: 'esnext'
|
|
1541
1543
|
},
|
|
@@ -1558,16 +1560,35 @@ export default css;
|
|
|
1558
1560
|
transpiled = transpiler.transformSync(content.toString());
|
|
1559
1561
|
} else {
|
|
1560
1562
|
// Node.js - use esbuild
|
|
1561
|
-
const { transformSync } = await import('esbuild');
|
|
1562
1563
|
const loader = ext === '.tsx' ? 'tsx' : 'ts';
|
|
1563
|
-
const
|
|
1564
|
-
loader: loader as any,
|
|
1565
|
-
format: 'esm',
|
|
1566
|
-
target: 'es2020',
|
|
1567
|
-
sourcemap: 'inline'
|
|
1568
|
-
});
|
|
1564
|
+
const { transformSync } = await import('esbuild');
|
|
1569
1565
|
|
|
1570
|
-
|
|
1566
|
+
if (config.mode === 'preview') {
|
|
1567
|
+
// Preview mode: transpile then obfuscate via esbuild-obfuscator-plugin's
|
|
1568
|
+
// underlying javascript-obfuscator library
|
|
1569
|
+
const { default: JavaScriptObfuscator } = await import('javascript-obfuscator');
|
|
1570
|
+
|
|
1571
|
+
const tsResult = transformSync(content.toString(), {
|
|
1572
|
+
loader: loader as any,
|
|
1573
|
+
format: 'esm',
|
|
1574
|
+
target: 'es2020',
|
|
1575
|
+
sourcemap: false
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
transpiled = JavaScriptObfuscator.obfuscate(tsResult.code, {
|
|
1579
|
+
compact: true,
|
|
1580
|
+
renameGlobals: false
|
|
1581
|
+
}).getObfuscatedCode();
|
|
1582
|
+
} else {
|
|
1583
|
+
// Dev mode: transpile with inline source maps
|
|
1584
|
+
const result = transformSync(content.toString(), {
|
|
1585
|
+
loader: loader as any,
|
|
1586
|
+
format: 'esm',
|
|
1587
|
+
target: 'es2020',
|
|
1588
|
+
sourcemap: 'inline'
|
|
1589
|
+
});
|
|
1590
|
+
transpiled = result.code;
|
|
1591
|
+
}
|
|
1571
1592
|
}
|
|
1572
1593
|
|
|
1573
1594
|
// Rewrite .ts imports to .js for browser compatibility
|
|
@@ -1604,7 +1625,7 @@ export default css;
|
|
|
1604
1625
|
// Inject HMR client and import map for HTML files
|
|
1605
1626
|
if (ext === '.html') {
|
|
1606
1627
|
const wsPath = normalizeBasePath(client.basePath);
|
|
1607
|
-
const hmrScript = createHMRScript(config.port, wsPath);
|
|
1628
|
+
const hmrScript = config.mode !== 'preview' ? createHMRScript(config.port, wsPath) : '';
|
|
1608
1629
|
let html = content.toString();
|
|
1609
1630
|
|
|
1610
1631
|
// If SSR is configured, extract and inject styles from SSR
|
|
@@ -1657,7 +1678,8 @@ export default css;
|
|
|
1657
1678
|
|
|
1658
1679
|
// Inject import map and SSR styles into <head>
|
|
1659
1680
|
const elitImportMap = await createElitImportMap(client.root, basePath, client.mode);
|
|
1660
|
-
const
|
|
1681
|
+
const modeScript = config.mode === 'preview' ? '<script>window.__ELIT_MODE__=\'preview\';</script>' : '';
|
|
1682
|
+
const headInjection = `${modeScript}${ssrStyles ? '\n' + ssrStyles : ''}\n${elitImportMap}`;
|
|
1661
1683
|
html = html.includes('</head>') ? html.replace('</head>', `${headInjection}</head>`) : html;
|
|
1662
1684
|
html = html.includes('</body>') ? html.replace('</body>', `${hmrScript}</body>`) : html + hmrScript;
|
|
1663
1685
|
content = Buffer.from(html);
|
|
@@ -1670,7 +1692,11 @@ export default css;
|
|
|
1670
1692
|
|
|
1671
1693
|
const headers: any = {
|
|
1672
1694
|
'Content-Type': mimeType,
|
|
1673
|
-
'Cache-Control': cacheControl
|
|
1695
|
+
'Cache-Control': cacheControl,
|
|
1696
|
+
'X-Content-Type-Options': 'nosniff',
|
|
1697
|
+
'X-Frame-Options': 'DENY',
|
|
1698
|
+
'X-XSS-Protection': '1; mode=block',
|
|
1699
|
+
'Referrer-Policy': 'strict-origin-when-cross-origin'
|
|
1674
1700
|
};
|
|
1675
1701
|
|
|
1676
1702
|
// Apply gzip compression for text-based files
|
|
@@ -1726,15 +1752,23 @@ export default css;
|
|
|
1726
1752
|
const basePath = normalizeBasePath(client.basePath);
|
|
1727
1753
|
html = rewriteRelativePaths(html, basePath);
|
|
1728
1754
|
|
|
1729
|
-
// Inject HMR script
|
|
1730
|
-
const hmrScript = createHMRScript(config.port, basePath);
|
|
1755
|
+
// Inject HMR script (dev mode only)
|
|
1756
|
+
const hmrScript = config.mode !== 'preview' ? createHMRScript(config.port, basePath) : '';
|
|
1731
1757
|
|
|
1732
1758
|
// Inject import map in head, HMR script in body
|
|
1733
1759
|
const elitImportMap = await createElitImportMap(client.root, basePath, client.mode);
|
|
1734
|
-
|
|
1760
|
+
const modeScript = config.mode === 'preview' ? '<script>window.__ELIT_MODE__=\'preview\';</script>\n' : '';
|
|
1761
|
+
html = html.includes('</head>') ? html.replace('</head>', `${modeScript}${elitImportMap}</head>`) : html;
|
|
1735
1762
|
html = html.includes('</body>') ? html.replace('</body>', `${hmrScript}</body>`) : html + hmrScript;
|
|
1736
1763
|
|
|
1737
|
-
res.writeHead(200, {
|
|
1764
|
+
res.writeHead(200, {
|
|
1765
|
+
'Content-Type': 'text/html',
|
|
1766
|
+
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
1767
|
+
'X-Content-Type-Options': 'nosniff',
|
|
1768
|
+
'X-Frame-Options': 'DENY',
|
|
1769
|
+
'X-XSS-Protection': '1; mode=block',
|
|
1770
|
+
'Referrer-Policy': 'strict-origin-when-cross-origin'
|
|
1771
|
+
});
|
|
1738
1772
|
res.end(html);
|
|
1739
1773
|
|
|
1740
1774
|
if (config.logging) console.log(`[200] SSR rendered`);
|
|
@@ -1744,111 +1778,117 @@ export default css;
|
|
|
1744
1778
|
}
|
|
1745
1779
|
}
|
|
1746
1780
|
|
|
1747
|
-
// WebSocket Server for HMR
|
|
1748
|
-
|
|
1781
|
+
// WebSocket Server for HMR - only in dev mode (not needed for preview)
|
|
1782
|
+
let wss: any = null;
|
|
1783
|
+
if (config.mode !== 'preview') {
|
|
1784
|
+
wss = new WebSocketServer({ server });
|
|
1749
1785
|
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1786
|
+
if (config.logging) {
|
|
1787
|
+
console.log('[HMR] WebSocket server initialized');
|
|
1788
|
+
}
|
|
1753
1789
|
|
|
1754
|
-
|
|
1755
|
-
|
|
1790
|
+
wss.on('connection', (ws: WebSocket, req: IncomingMessage) => {
|
|
1791
|
+
wsClients.add(ws);
|
|
1756
1792
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1793
|
+
const message: HMRMessage = { type: 'connected', timestamp: Date.now() };
|
|
1794
|
+
ws.send(JSON.stringify(message));
|
|
1759
1795
|
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1796
|
+
if (config.logging) {
|
|
1797
|
+
console.log('[HMR] Client connected from', req.socket.remoteAddress);
|
|
1798
|
+
}
|
|
1763
1799
|
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1800
|
+
// Handle incoming messages
|
|
1801
|
+
ws.on('message', (data: string) => {
|
|
1802
|
+
try {
|
|
1803
|
+
const msg = JSON.parse(data.toString());
|
|
1768
1804
|
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1805
|
+
// Handle state subscription
|
|
1806
|
+
if (msg.type === 'state:subscribe') {
|
|
1807
|
+
stateManager.subscribe(msg.key, ws);
|
|
1808
|
+
if (config.logging) {
|
|
1809
|
+
console.log(`[State] Client subscribed to "${msg.key}"`);
|
|
1810
|
+
}
|
|
1774
1811
|
}
|
|
1775
|
-
}
|
|
1776
1812
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1813
|
+
// Handle state unsubscribe
|
|
1814
|
+
else if (msg.type === 'state:unsubscribe') {
|
|
1815
|
+
stateManager.unsubscribe(msg.key, ws);
|
|
1816
|
+
if (config.logging) {
|
|
1817
|
+
console.log(`[State] Client unsubscribed from "${msg.key}"`);
|
|
1818
|
+
}
|
|
1782
1819
|
}
|
|
1783
|
-
}
|
|
1784
1820
|
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1821
|
+
// Handle state change from client
|
|
1822
|
+
else if (msg.type === 'state:change') {
|
|
1823
|
+
stateManager.handleStateChange(msg.key, msg.value);
|
|
1824
|
+
if (config.logging) {
|
|
1825
|
+
console.log(`[State] Client updated "${msg.key}"`);
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
} catch (error) {
|
|
1788
1829
|
if (config.logging) {
|
|
1789
|
-
console.
|
|
1830
|
+
console.error('[WebSocket] Message parse error:', error);
|
|
1790
1831
|
}
|
|
1791
1832
|
}
|
|
1792
|
-
}
|
|
1833
|
+
});
|
|
1834
|
+
|
|
1835
|
+
ws.on('close', () => {
|
|
1836
|
+
wsClients.delete(ws);
|
|
1837
|
+
stateManager.unsubscribeAll(ws);
|
|
1793
1838
|
if (config.logging) {
|
|
1794
|
-
console.
|
|
1839
|
+
console.log('[HMR] Client disconnected');
|
|
1795
1840
|
}
|
|
1796
|
-
}
|
|
1841
|
+
});
|
|
1797
1842
|
});
|
|
1843
|
+
}
|
|
1798
1844
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1845
|
+
// File watcher - only in dev mode (not needed for preview)
|
|
1846
|
+
let watcher: any = null;
|
|
1847
|
+
if (config.mode !== 'preview') {
|
|
1848
|
+
const watchPaths = normalizedClients.flatMap(client =>
|
|
1849
|
+
config.watch.map(pattern => join(client.root, pattern))
|
|
1850
|
+
);
|
|
1851
|
+
|
|
1852
|
+
watcher = watch(watchPaths, {
|
|
1853
|
+
ignored: (path: string) => config.ignore.some(pattern => path.includes(pattern.replace('/**', '').replace('**/', ''))),
|
|
1854
|
+
ignoreInitial: true,
|
|
1855
|
+
persistent: true
|
|
1805
1856
|
});
|
|
1806
|
-
});
|
|
1807
|
-
|
|
1808
|
-
// File watcher - watch all client roots
|
|
1809
|
-
const watchPaths = normalizedClients.flatMap(client =>
|
|
1810
|
-
config.watch.map(pattern => join(client.root, pattern))
|
|
1811
|
-
);
|
|
1812
1857
|
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
// Client disconnected - will be removed from clients set by close event
|
|
1830
|
-
return;
|
|
1831
|
-
}
|
|
1832
|
-
});
|
|
1833
|
-
}
|
|
1858
|
+
watcher.on('change', (path: string) => {
|
|
1859
|
+
if (config.logging) console.log(`[HMR] File changed: ${path}`);
|
|
1860
|
+
const message = JSON.stringify({ type: 'update', path, timestamp: Date.now() } as HMRMessage);
|
|
1861
|
+
// Broadcast to all open clients with error handling
|
|
1862
|
+
wsClients.forEach(client => {
|
|
1863
|
+
if (client.readyState === ReadyState.OPEN) {
|
|
1864
|
+
client.send(message, {}, (err?: Error) => {
|
|
1865
|
+
// Silently ignore connection errors during HMR
|
|
1866
|
+
const code = (err as any)?.code;
|
|
1867
|
+
if (code === 'ECONNABORTED' || code === 'ECONNRESET' || code === 'EPIPE' || code === 'WS_NOT_OPEN') {
|
|
1868
|
+
// Client disconnected - will be removed from clients set by close event
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
});
|
|
1834
1874
|
});
|
|
1835
|
-
});
|
|
1836
1875
|
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1876
|
+
watcher.on('add', (path: string) => {
|
|
1877
|
+
if (config.logging) console.log(`[HMR] File added: ${path}`);
|
|
1878
|
+
const message = JSON.stringify({ type: 'update', path, timestamp: Date.now() } as HMRMessage);
|
|
1879
|
+
wsClients.forEach(client => {
|
|
1880
|
+
if (client.readyState === ReadyState.OPEN) client.send(message, {});
|
|
1881
|
+
});
|
|
1842
1882
|
});
|
|
1843
|
-
});
|
|
1844
1883
|
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1884
|
+
watcher.on('unlink', (path: string) => {
|
|
1885
|
+
if (config.logging) console.log(`[HMR] File removed: ${path}`);
|
|
1886
|
+
const message = JSON.stringify({ type: 'reload', path, timestamp: Date.now() } as HMRMessage);
|
|
1887
|
+
wsClients.forEach(client => {
|
|
1888
|
+
if (client.readyState === ReadyState.OPEN) client.send(message, {});
|
|
1889
|
+
});
|
|
1850
1890
|
});
|
|
1851
|
-
}
|
|
1891
|
+
}
|
|
1852
1892
|
|
|
1853
1893
|
// Increase max listeners to prevent warnings
|
|
1854
1894
|
server.setMaxListeners(20);
|
|
@@ -1873,7 +1913,7 @@ export default css;
|
|
|
1873
1913
|
}
|
|
1874
1914
|
}
|
|
1875
1915
|
|
|
1876
|
-
console.log(`\n[HMR] Watching for file changes...\n`);
|
|
1916
|
+
if (config.mode !== 'preview') console.log(`\n[HMR] Watching for file changes...\n`);
|
|
1877
1917
|
}
|
|
1878
1918
|
|
|
1879
1919
|
// Open browser to first client
|
|
@@ -1897,10 +1937,12 @@ export default css;
|
|
|
1897
1937
|
if (isClosing) return;
|
|
1898
1938
|
isClosing = true;
|
|
1899
1939
|
if (config.logging) console.log('\n[Server] Shutting down...');
|
|
1900
|
-
await watcher.close();
|
|
1901
|
-
wss
|
|
1902
|
-
|
|
1903
|
-
|
|
1940
|
+
if (watcher) await watcher.close();
|
|
1941
|
+
if (wss) {
|
|
1942
|
+
wss.close();
|
|
1943
|
+
wsClients.forEach(client => client.close());
|
|
1944
|
+
wsClients.clear();
|
|
1945
|
+
}
|
|
1904
1946
|
return new Promise<void>((resolve) => {
|
|
1905
1947
|
server.close(() => {
|
|
1906
1948
|
if (config.logging) console.log('[Server] Closed');
|