almostnode 0.2.1 → 0.2.3
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/frameworks/next-dev-server.d.ts +5 -0
- package/dist/frameworks/next-dev-server.d.ts.map +1 -1
- package/dist/index.cjs +81 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +77 -26
- package/dist/index.mjs.map +1 -1
- package/dist/sandbox-helpers.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/frameworks/next-dev-server.ts +75 -15
- package/src/sandbox-helpers.ts +28 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-helpers.d.ts","sourceRoot":"","sources":["../src/sandbox-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"sandbox-helpers.d.ts","sourceRoot":"","sources":["../src/sandbox-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiDH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,kBAAkB,GAAG,MAAW,GAAG,MAAM,CA6GhF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAY/C;AAED,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;CAEtE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,2BAA2B,GAAG,MAAW,GAAG;IACxF,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAuBA;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAmB/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "almostnode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Node.js in your browser. Just like that.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -102,4 +102,4 @@
|
|
|
102
102
|
"vite": "^5.4.0",
|
|
103
103
|
"vitest": "^4.0.18"
|
|
104
104
|
}
|
|
105
|
-
}
|
|
105
|
+
}
|
|
@@ -816,6 +816,11 @@ export class NextDevServer extends DevServer {
|
|
|
816
816
|
return this.serveNextShim(pathname);
|
|
817
817
|
}
|
|
818
818
|
|
|
819
|
+
// Serve page components for client-side navigation
|
|
820
|
+
if (pathname.startsWith('/_next/pages/')) {
|
|
821
|
+
return this.servePageComponent(pathname);
|
|
822
|
+
}
|
|
823
|
+
|
|
819
824
|
// Static assets from /_next/static/*
|
|
820
825
|
if (pathname.startsWith('/_next/static/')) {
|
|
821
826
|
return this.serveStaticAsset(pathname);
|
|
@@ -895,6 +900,28 @@ export class NextDevServer extends DevServer {
|
|
|
895
900
|
return this.notFound(pathname);
|
|
896
901
|
}
|
|
897
902
|
|
|
903
|
+
/**
|
|
904
|
+
* Serve page components for client-side navigation
|
|
905
|
+
* Maps /_next/pages/index.js → /pages/index.jsx (transformed)
|
|
906
|
+
*/
|
|
907
|
+
private async servePageComponent(pathname: string): Promise<ResponseData> {
|
|
908
|
+
// Extract the route from /_next/pages/about.js → /about
|
|
909
|
+
const route = pathname
|
|
910
|
+
.replace('/_next/pages', '')
|
|
911
|
+
.replace(/\.js$/, '');
|
|
912
|
+
|
|
913
|
+
// Resolve the actual page file
|
|
914
|
+
const pageFile = this.resolvePageFile(route);
|
|
915
|
+
|
|
916
|
+
if (!pageFile) {
|
|
917
|
+
return this.notFound(pathname);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Transform and serve the page component as a JS module
|
|
921
|
+
// Use the actual file path (pageFile) for both reading and determining the loader
|
|
922
|
+
return this.transformAndServe(pageFile, pageFile);
|
|
923
|
+
}
|
|
924
|
+
|
|
898
925
|
/**
|
|
899
926
|
* Handle API route requests
|
|
900
927
|
*/
|
|
@@ -1837,30 +1864,63 @@ export class NextDevServer extends DevServer {
|
|
|
1837
1864
|
<script type="module">
|
|
1838
1865
|
import React from 'react';
|
|
1839
1866
|
import ReactDOM from 'react-dom/client';
|
|
1840
|
-
import Page from '${pageModulePath}';
|
|
1841
1867
|
|
|
1842
|
-
|
|
1843
|
-
function App() {
|
|
1844
|
-
const [currentPath, setCurrentPath] = React.useState(window.location.pathname);
|
|
1868
|
+
const virtualBase = '${virtualPrefix}';
|
|
1845
1869
|
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1870
|
+
// Convert URL path to page module path
|
|
1871
|
+
function getPageModulePath(pathname) {
|
|
1872
|
+
let route = pathname;
|
|
1873
|
+
if (route.startsWith(virtualBase)) {
|
|
1874
|
+
route = route.slice(virtualBase.length);
|
|
1875
|
+
}
|
|
1876
|
+
route = route.replace(/^\\/+/, '/') || '/';
|
|
1877
|
+
const modulePath = route === '/' ? '/index' : route;
|
|
1878
|
+
return virtualBase + '/_next/pages' + modulePath + '.js';
|
|
1879
|
+
}
|
|
1852
1880
|
|
|
1853
|
-
|
|
1854
|
-
|
|
1881
|
+
// Dynamic page loader
|
|
1882
|
+
async function loadPage(pathname) {
|
|
1883
|
+
const modulePath = getPageModulePath(pathname);
|
|
1884
|
+
try {
|
|
1885
|
+
const module = await import(/* @vite-ignore */ modulePath);
|
|
1886
|
+
return module.default;
|
|
1887
|
+
} catch (e) {
|
|
1888
|
+
console.error('[Navigation] Failed to load:', modulePath, e);
|
|
1889
|
+
return null;
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
// Router component
|
|
1894
|
+
function Router() {
|
|
1895
|
+
const [Page, setPage] = React.useState(null);
|
|
1896
|
+
const [path, setPath] = React.useState(window.location.pathname);
|
|
1897
|
+
|
|
1898
|
+
React.useEffect(() => {
|
|
1899
|
+
loadPage(path).then(C => C && setPage(() => C));
|
|
1855
1900
|
}, []);
|
|
1856
1901
|
|
|
1902
|
+
React.useEffect(() => {
|
|
1903
|
+
const handleNavigation = async () => {
|
|
1904
|
+
const newPath = window.location.pathname;
|
|
1905
|
+
if (newPath !== path) {
|
|
1906
|
+
setPath(newPath);
|
|
1907
|
+
const C = await loadPage(newPath);
|
|
1908
|
+
if (C) setPage(() => C);
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
window.addEventListener('popstate', handleNavigation);
|
|
1912
|
+
return () => window.removeEventListener('popstate', handleNavigation);
|
|
1913
|
+
}, [path]);
|
|
1914
|
+
|
|
1915
|
+
if (!Page) return null;
|
|
1857
1916
|
return React.createElement(Page);
|
|
1858
1917
|
}
|
|
1859
1918
|
|
|
1919
|
+
// Mark that we've initialized (for testing no-reload)
|
|
1920
|
+
window.__NEXT_INITIALIZED__ = Date.now();
|
|
1921
|
+
|
|
1860
1922
|
ReactDOM.createRoot(document.getElementById('__next')).render(
|
|
1861
|
-
React.createElement(React.StrictMode, null,
|
|
1862
|
-
React.createElement(App)
|
|
1863
|
-
)
|
|
1923
|
+
React.createElement(React.StrictMode, null, React.createElement(Router))
|
|
1864
1924
|
);
|
|
1865
1925
|
</script>
|
|
1866
1926
|
</body>
|
package/src/sandbox-helpers.ts
CHANGED
|
@@ -5,27 +5,44 @@
|
|
|
5
5
|
* to provide browser-enforced isolation from the main application.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import * as fs from 'fs';
|
|
9
|
-
import * as path from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
13
|
-
// @ts-ignore - import.meta.url is available in ESM
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
|
|
16
8
|
/**
|
|
17
9
|
* Get the contents of the service worker file.
|
|
18
|
-
* Returns null if
|
|
10
|
+
* Returns null if running in browser or file is not found.
|
|
11
|
+
*
|
|
12
|
+
* Note: This function only works in Node.js. In the browser, it returns null.
|
|
19
13
|
*/
|
|
20
14
|
function getServiceWorkerContent(): string | null {
|
|
15
|
+
// Only works in Node.js - check for presence of require
|
|
16
|
+
if (typeof require === 'undefined') {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
21
20
|
try {
|
|
21
|
+
// Dynamic requires to avoid bundling Node.js modules in browser build
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
25
|
+
const path = require('path');
|
|
26
|
+
|
|
27
|
+
// __dirname equivalent for ESM
|
|
28
|
+
let dirname: string;
|
|
29
|
+
try {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
31
|
+
const url = require('url');
|
|
32
|
+
// @ts-ignore - import.meta.url is available in ESM
|
|
33
|
+
dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
34
|
+
} catch {
|
|
35
|
+
// Fallback for CommonJS
|
|
36
|
+
dirname = __dirname;
|
|
37
|
+
}
|
|
38
|
+
|
|
22
39
|
// Try dist directory first (when running from built package)
|
|
23
|
-
let swPath = path.join(
|
|
40
|
+
let swPath = path.join(dirname, '__sw__.js');
|
|
24
41
|
if (fs.existsSync(swPath)) {
|
|
25
42
|
return fs.readFileSync(swPath, 'utf-8');
|
|
26
43
|
}
|
|
27
44
|
// Try relative to src (when running from source)
|
|
28
|
-
swPath = path.join(
|
|
45
|
+
swPath = path.join(dirname, '../dist/__sw__.js');
|
|
29
46
|
if (fs.existsSync(swPath)) {
|
|
30
47
|
return fs.readFileSync(swPath, 'utf-8');
|
|
31
48
|
}
|