@run0/jiki 0.1.0
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/browser-bundle.d.ts +40 -0
- package/dist/builtins.d.ts +22 -0
- package/dist/code-transform.d.ts +7 -0
- package/dist/config/cdn.d.ts +13 -0
- package/dist/container.d.ts +101 -0
- package/dist/dev-server.d.ts +69 -0
- package/dist/errors.d.ts +19 -0
- package/dist/frameworks/code-transforms.d.ts +32 -0
- package/dist/frameworks/next-api-handler.d.ts +72 -0
- package/dist/frameworks/next-dev-server.d.ts +141 -0
- package/dist/frameworks/next-html-generator.d.ts +36 -0
- package/dist/frameworks/next-route-resolver.d.ts +19 -0
- package/dist/frameworks/next-shims.d.ts +78 -0
- package/dist/frameworks/remix-dev-server.d.ts +47 -0
- package/dist/frameworks/sveltekit-dev-server.d.ts +43 -0
- package/dist/frameworks/vite-dev-server.d.ts +50 -0
- package/dist/fs-errors.d.ts +36 -0
- package/dist/index.cjs +14916 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.mjs +14898 -0
- package/dist/index.mjs.map +1 -0
- package/dist/kernel.d.ts +48 -0
- package/dist/memfs.d.ts +144 -0
- package/dist/metrics.d.ts +78 -0
- package/dist/module-resolver.d.ts +60 -0
- package/dist/network-interceptor.d.ts +71 -0
- package/dist/npm/cache.d.ts +76 -0
- package/dist/npm/index.d.ts +60 -0
- package/dist/npm/lockfile-reader.d.ts +32 -0
- package/dist/npm/pnpm.d.ts +18 -0
- package/dist/npm/registry.d.ts +45 -0
- package/dist/npm/resolver.d.ts +39 -0
- package/dist/npm/sync-installer.d.ts +18 -0
- package/dist/npm/tarball.d.ts +4 -0
- package/dist/npm/workspaces.d.ts +46 -0
- package/dist/persistence.d.ts +94 -0
- package/dist/plugin.d.ts +156 -0
- package/dist/polyfills/assert.d.ts +30 -0
- package/dist/polyfills/child_process.d.ts +116 -0
- package/dist/polyfills/chokidar.d.ts +18 -0
- package/dist/polyfills/crypto.d.ts +49 -0
- package/dist/polyfills/events.d.ts +28 -0
- package/dist/polyfills/fs.d.ts +82 -0
- package/dist/polyfills/http.d.ts +147 -0
- package/dist/polyfills/module.d.ts +29 -0
- package/dist/polyfills/net.d.ts +53 -0
- package/dist/polyfills/os.d.ts +91 -0
- package/dist/polyfills/path.d.ts +96 -0
- package/dist/polyfills/perf_hooks.d.ts +21 -0
- package/dist/polyfills/process.d.ts +99 -0
- package/dist/polyfills/querystring.d.ts +15 -0
- package/dist/polyfills/readdirp.d.ts +18 -0
- package/dist/polyfills/readline.d.ts +32 -0
- package/dist/polyfills/stream.d.ts +106 -0
- package/dist/polyfills/stubs.d.ts +737 -0
- package/dist/polyfills/tty.d.ts +25 -0
- package/dist/polyfills/url.d.ts +41 -0
- package/dist/polyfills/util.d.ts +61 -0
- package/dist/polyfills/v8.d.ts +43 -0
- package/dist/polyfills/vm.d.ts +76 -0
- package/dist/polyfills/worker-threads.d.ts +77 -0
- package/dist/polyfills/ws.d.ts +32 -0
- package/dist/polyfills/zlib.d.ts +87 -0
- package/dist/runtime-helpers.d.ts +4 -0
- package/dist/runtime-interface.d.ts +39 -0
- package/dist/sandbox.d.ts +69 -0
- package/dist/server-bridge.d.ts +55 -0
- package/dist/shell-commands.d.ts +2 -0
- package/dist/shell.d.ts +101 -0
- package/dist/transpiler.d.ts +47 -0
- package/dist/type-checker.d.ts +57 -0
- package/dist/types/package-json.d.ts +17 -0
- package/dist/utils/binary-encoding.d.ts +4 -0
- package/dist/utils/hash.d.ts +6 -0
- package/dist/utils/safe-path.d.ts +6 -0
- package/dist/worker-runtime.d.ts +34 -0
- package/package.json +59 -0
- package/src/browser-bundle.ts +498 -0
- package/src/builtins.ts +222 -0
- package/src/code-transform.ts +183 -0
- package/src/config/cdn.ts +17 -0
- package/src/container.ts +343 -0
- package/src/dev-server.ts +322 -0
- package/src/errors.ts +604 -0
- package/src/frameworks/code-transforms.ts +667 -0
- package/src/frameworks/next-api-handler.ts +366 -0
- package/src/frameworks/next-dev-server.ts +1252 -0
- package/src/frameworks/next-html-generator.ts +585 -0
- package/src/frameworks/next-route-resolver.ts +521 -0
- package/src/frameworks/next-shims.ts +1084 -0
- package/src/frameworks/remix-dev-server.ts +163 -0
- package/src/frameworks/sveltekit-dev-server.ts +197 -0
- package/src/frameworks/vite-dev-server.ts +370 -0
- package/src/fs-errors.ts +118 -0
- package/src/index.ts +188 -0
- package/src/kernel.ts +381 -0
- package/src/memfs.ts +1006 -0
- package/src/metrics.ts +140 -0
- package/src/module-resolver.ts +511 -0
- package/src/network-interceptor.ts +143 -0
- package/src/npm/cache.ts +172 -0
- package/src/npm/index.ts +377 -0
- package/src/npm/lockfile-reader.ts +105 -0
- package/src/npm/pnpm.ts +108 -0
- package/src/npm/registry.ts +120 -0
- package/src/npm/resolver.ts +339 -0
- package/src/npm/sync-installer.ts +217 -0
- package/src/npm/tarball.ts +136 -0
- package/src/npm/workspaces.ts +255 -0
- package/src/persistence.ts +235 -0
- package/src/plugin.ts +293 -0
- package/src/polyfills/assert.ts +164 -0
- package/src/polyfills/child_process.ts +535 -0
- package/src/polyfills/chokidar.ts +52 -0
- package/src/polyfills/crypto.ts +433 -0
- package/src/polyfills/events.ts +178 -0
- package/src/polyfills/fs.ts +297 -0
- package/src/polyfills/http.ts +478 -0
- package/src/polyfills/module.ts +97 -0
- package/src/polyfills/net.ts +123 -0
- package/src/polyfills/os.ts +108 -0
- package/src/polyfills/path.ts +169 -0
- package/src/polyfills/perf_hooks.ts +30 -0
- package/src/polyfills/process.ts +349 -0
- package/src/polyfills/querystring.ts +66 -0
- package/src/polyfills/readdirp.ts +72 -0
- package/src/polyfills/readline.ts +80 -0
- package/src/polyfills/stream.ts +610 -0
- package/src/polyfills/stubs.ts +600 -0
- package/src/polyfills/tty.ts +43 -0
- package/src/polyfills/url.ts +97 -0
- package/src/polyfills/util.ts +173 -0
- package/src/polyfills/v8.ts +62 -0
- package/src/polyfills/vm.ts +111 -0
- package/src/polyfills/worker-threads.ts +189 -0
- package/src/polyfills/ws.ts +73 -0
- package/src/polyfills/zlib.ts +244 -0
- package/src/runtime-helpers.ts +83 -0
- package/src/runtime-interface.ts +46 -0
- package/src/sandbox.ts +178 -0
- package/src/server-bridge.ts +473 -0
- package/src/service-worker.ts +153 -0
- package/src/shell-commands.ts +708 -0
- package/src/shell.ts +795 -0
- package/src/transpiler.ts +282 -0
- package/src/type-checker.ts +241 -0
- package/src/types/package-json.ts +17 -0
- package/src/utils/binary-encoding.ts +38 -0
- package/src/utils/hash.ts +24 -0
- package/src/utils/safe-path.ts +38 -0
- package/src/worker-runtime.ts +42 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remix-compatible dev server for jiki.
|
|
3
|
+
*
|
|
4
|
+
* Extends the ViteDevServer with Remix's file-based routing conventions:
|
|
5
|
+
* - `routes/` directory for flat file routing
|
|
6
|
+
* - `loader`/`action` exports for data loading
|
|
7
|
+
* - Nested layouts via dot-delimited filenames (e.g. `routes/dashboard.settings.tsx`)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ViteDevServer, type ViteDevServerOptions } from "./vite-dev-server";
|
|
11
|
+
import { MemFS } from "../memfs";
|
|
12
|
+
import { BufferImpl as Buffer } from "../polyfills/stream";
|
|
13
|
+
import * as pathShim from "../polyfills/path";
|
|
14
|
+
import type { ResponseData } from "../dev-server";
|
|
15
|
+
|
|
16
|
+
export interface RemixDevServerOptions extends ViteDevServerOptions {
|
|
17
|
+
/** Routes directory (default: `/app/routes`). */
|
|
18
|
+
routesDir?: string;
|
|
19
|
+
/** App directory (default: `/app`). */
|
|
20
|
+
appDir?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RemixRoute {
|
|
24
|
+
/** URL route path. */
|
|
25
|
+
route: string;
|
|
26
|
+
/** File path in the VFS. */
|
|
27
|
+
filePath: string;
|
|
28
|
+
/** Whether this is a layout route. */
|
|
29
|
+
isLayout: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class RemixDevServer extends ViteDevServer {
|
|
33
|
+
private routesDir: string;
|
|
34
|
+
private appDir: string;
|
|
35
|
+
|
|
36
|
+
constructor(vfs: MemFS, options: RemixDevServerOptions) {
|
|
37
|
+
super(vfs, { ...options, framework: "react" });
|
|
38
|
+
this.routesDir = options.routesDir || "/app/routes";
|
|
39
|
+
this.appDir = options.appDir || "/app";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async handleRequest(
|
|
43
|
+
method: string,
|
|
44
|
+
url: string,
|
|
45
|
+
headers: Record<string, string>,
|
|
46
|
+
body?: Buffer,
|
|
47
|
+
): Promise<ResponseData> {
|
|
48
|
+
const parsed = new URL(url, "http://localhost");
|
|
49
|
+
const pathname = decodeURIComponent(parsed.pathname);
|
|
50
|
+
|
|
51
|
+
// Try to resolve as a Remix route
|
|
52
|
+
const route = this.resolveRoute(pathname);
|
|
53
|
+
if (route) {
|
|
54
|
+
return this.addCorsHeaders(this.serveRemixPage(route, pathname));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fall through to ViteDevServer
|
|
58
|
+
return super.handleRequest(method, url, headers, body);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolve a URL pathname to a Remix route file.
|
|
63
|
+
* Remix uses flat file routing with dot-delimited nesting:
|
|
64
|
+
* - `routes/_index.tsx` → `/`
|
|
65
|
+
* - `routes/about.tsx` → `/about`
|
|
66
|
+
* - `routes/dashboard.settings.tsx` → `/dashboard/settings`
|
|
67
|
+
*/
|
|
68
|
+
private resolveRoute(pathname: string): RemixRoute | null {
|
|
69
|
+
// Try _index for root
|
|
70
|
+
if (pathname === "/") {
|
|
71
|
+
const indexFile = this.findRouteFile("_index");
|
|
72
|
+
if (indexFile)
|
|
73
|
+
return { route: "/", filePath: indexFile, isLayout: false };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Convert URL path to flat filename
|
|
77
|
+
const segments = pathname.split("/").filter(Boolean);
|
|
78
|
+
const flatName = segments.join(".");
|
|
79
|
+
|
|
80
|
+
const file = this.findRouteFile(flatName);
|
|
81
|
+
if (file) return { route: pathname, filePath: file, isLayout: false };
|
|
82
|
+
|
|
83
|
+
// Try index under a layout
|
|
84
|
+
const indexName = flatName ? `${flatName}._index` : "_index";
|
|
85
|
+
const indexFile = this.findRouteFile(indexName);
|
|
86
|
+
if (indexFile)
|
|
87
|
+
return { route: pathname, filePath: indexFile, isLayout: false };
|
|
88
|
+
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private findRouteFile(name: string): string | null {
|
|
93
|
+
for (const ext of [".tsx", ".ts", ".jsx", ".js"]) {
|
|
94
|
+
const filePath = pathShim.join(this.routesDir, `${name}${ext}`);
|
|
95
|
+
if (this.exists(filePath)) return filePath;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private serveRemixPage(route: RemixRoute, pathname: string): ResponseData {
|
|
101
|
+
const rootPath = pathShim.join(this.appDir, "root.tsx");
|
|
102
|
+
const hasRoot = this.exists(rootPath);
|
|
103
|
+
|
|
104
|
+
const html = `<!DOCTYPE html>
|
|
105
|
+
<html>
|
|
106
|
+
<head>
|
|
107
|
+
<meta charset="utf-8" />
|
|
108
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
109
|
+
<title>Remix App</title>
|
|
110
|
+
<script type="module" src="/@vite/client"></script>
|
|
111
|
+
</head>
|
|
112
|
+
<body>
|
|
113
|
+
<div id="root"></div>
|
|
114
|
+
${hasRoot ? `<script type="module" src="${rootPath}"></script>` : ""}
|
|
115
|
+
<script type="module" src="${route.filePath}"></script>
|
|
116
|
+
</body>
|
|
117
|
+
</html>`;
|
|
118
|
+
const buf = Buffer.from(html);
|
|
119
|
+
return {
|
|
120
|
+
statusCode: 200,
|
|
121
|
+
statusMessage: "OK",
|
|
122
|
+
headers: {
|
|
123
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
124
|
+
"Content-Length": String(buf.length),
|
|
125
|
+
"Cache-Control": "no-cache",
|
|
126
|
+
},
|
|
127
|
+
body: buf,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Discover all routes in the Remix routes directory.
|
|
133
|
+
*/
|
|
134
|
+
discoverRoutes(): RemixRoute[] {
|
|
135
|
+
const routes: RemixRoute[] = [];
|
|
136
|
+
try {
|
|
137
|
+
const entries = this.vfs.readdirSync(this.routesDir);
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
if (!entry.match(/\.(tsx?|jsx?)$/)) continue;
|
|
140
|
+
const name = entry.replace(/\.(tsx?|jsx?)$/, "");
|
|
141
|
+
const filePath = pathShim.join(this.routesDir, entry);
|
|
142
|
+
const route = this.flatNameToRoute(name);
|
|
143
|
+
routes.push({ route, filePath, isLayout: name.includes("_layout") });
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
/* routes dir may not exist */
|
|
147
|
+
}
|
|
148
|
+
return routes;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private flatNameToRoute(name: string): string {
|
|
152
|
+
if (name === "_index") return "/";
|
|
153
|
+
// Convert dots to slashes, handle special chars
|
|
154
|
+
return (
|
|
155
|
+
"/" +
|
|
156
|
+
name
|
|
157
|
+
.replace(/\._index$/, "")
|
|
158
|
+
.replace(/\./g, "/")
|
|
159
|
+
.replace(/^\$/, ":")
|
|
160
|
+
.replace(/\/\$/g, "/:")
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvelteKit-compatible dev server for jiki.
|
|
3
|
+
*
|
|
4
|
+
* Extends the ViteDevServer with SvelteKit's file-based routing conventions:
|
|
5
|
+
* - `+page.svelte` for pages
|
|
6
|
+
* - `+layout.svelte` for layouts
|
|
7
|
+
* - `+server.ts` for API routes
|
|
8
|
+
* - `+error.svelte` for error pages
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ViteDevServer, type ViteDevServerOptions } from "./vite-dev-server";
|
|
12
|
+
import { MemFS } from "../memfs";
|
|
13
|
+
import { BufferImpl as Buffer } from "../polyfills/stream";
|
|
14
|
+
import * as pathShim from "../polyfills/path";
|
|
15
|
+
import type { ResponseData } from "../dev-server";
|
|
16
|
+
|
|
17
|
+
export interface SvelteKitDevServerOptions extends ViteDevServerOptions {
|
|
18
|
+
/** Routes directory (default: `/src/routes`). */
|
|
19
|
+
routesDir?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SvelteKitRoute {
|
|
23
|
+
route: string;
|
|
24
|
+
pagePath?: string;
|
|
25
|
+
layoutPath?: string;
|
|
26
|
+
serverPath?: string;
|
|
27
|
+
errorPath?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class SvelteKitDevServer extends ViteDevServer {
|
|
31
|
+
private routesDir: string;
|
|
32
|
+
|
|
33
|
+
constructor(vfs: MemFS, options: SvelteKitDevServerOptions) {
|
|
34
|
+
super(vfs, { ...options, framework: "svelte" });
|
|
35
|
+
this.routesDir = options.routesDir || "/src/routes";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async handleRequest(
|
|
39
|
+
method: string,
|
|
40
|
+
url: string,
|
|
41
|
+
headers: Record<string, string>,
|
|
42
|
+
body?: Buffer,
|
|
43
|
+
): Promise<ResponseData> {
|
|
44
|
+
const parsed = new URL(url, "http://localhost");
|
|
45
|
+
const pathname = decodeURIComponent(parsed.pathname);
|
|
46
|
+
|
|
47
|
+
// Check for +server.ts API routes first
|
|
48
|
+
const serverRoute = this.resolveServerRoute(pathname);
|
|
49
|
+
if (serverRoute) {
|
|
50
|
+
return this.addCorsHeaders(await this.serveTransformedFile(serverRoute));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check for +page.svelte routes
|
|
54
|
+
const pageRoute = this.resolvePageRoute(pathname);
|
|
55
|
+
if (pageRoute) {
|
|
56
|
+
return this.addCorsHeaders(this.serveSvelteKitPage(pageRoute));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Fall through to ViteDevServer for static files, CSS, etc.
|
|
60
|
+
return super.handleRequest(method, url, headers, body);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private resolvePageRoute(pathname: string): SvelteKitRoute | null {
|
|
64
|
+
const routePath = pathname === "/" ? "" : pathname;
|
|
65
|
+
const dir = pathShim.join(this.routesDir, routePath);
|
|
66
|
+
|
|
67
|
+
const pagePath = pathShim.join(dir, "+page.svelte");
|
|
68
|
+
if (!this.exists(pagePath)) return null;
|
|
69
|
+
|
|
70
|
+
const layoutPath = this.findLayout(dir);
|
|
71
|
+
const errorPath = this.findError(dir);
|
|
72
|
+
|
|
73
|
+
return { route: pathname, pagePath, layoutPath, errorPath };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private resolveServerRoute(pathname: string): string | null {
|
|
77
|
+
const routePath = pathname === "/" ? "" : pathname;
|
|
78
|
+
const dir = pathShim.join(this.routesDir, routePath);
|
|
79
|
+
|
|
80
|
+
for (const ext of [".ts", ".js"]) {
|
|
81
|
+
const serverPath = pathShim.join(dir, `+server${ext}`);
|
|
82
|
+
if (this.exists(serverPath)) return serverPath;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private findLayout(dir: string): string | undefined {
|
|
88
|
+
let current = dir;
|
|
89
|
+
while (current.startsWith(this.routesDir)) {
|
|
90
|
+
const layoutPath = pathShim.join(current, "+layout.svelte");
|
|
91
|
+
if (this.exists(layoutPath)) return layoutPath;
|
|
92
|
+
current = pathShim.dirname(current);
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private findError(dir: string): string | undefined {
|
|
98
|
+
const errorPath = pathShim.join(dir, "+error.svelte");
|
|
99
|
+
return this.exists(errorPath) ? errorPath : undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private serveSvelteKitPage(route: SvelteKitRoute): ResponseData {
|
|
103
|
+
const html = this.generateSvelteKitHtml(route);
|
|
104
|
+
const buf = Buffer.from(html);
|
|
105
|
+
return {
|
|
106
|
+
statusCode: 200,
|
|
107
|
+
statusMessage: "OK",
|
|
108
|
+
headers: {
|
|
109
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
110
|
+
"Content-Length": String(buf.length),
|
|
111
|
+
"Cache-Control": "no-cache",
|
|
112
|
+
},
|
|
113
|
+
body: buf,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private async serveTransformedFile(filePath: string): Promise<ResponseData> {
|
|
118
|
+
// Delegate to the parent ViteDevServer's transform pipeline
|
|
119
|
+
return super.handleRequest(
|
|
120
|
+
"GET",
|
|
121
|
+
`http://localhost/${filePath.replace(/^\//, "")}`,
|
|
122
|
+
{},
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private generateSvelteKitHtml(route: SvelteKitRoute): string {
|
|
127
|
+
const pageSource = route.pagePath
|
|
128
|
+
? this.safeRead(route.pagePath)
|
|
129
|
+
: "<p>Page not found</p>";
|
|
130
|
+
const layoutSource = route.layoutPath
|
|
131
|
+
? this.safeRead(route.layoutPath)
|
|
132
|
+
: null;
|
|
133
|
+
|
|
134
|
+
return `<!DOCTYPE html>
|
|
135
|
+
<html>
|
|
136
|
+
<head>
|
|
137
|
+
<meta charset="utf-8" />
|
|
138
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
139
|
+
<title>SvelteKit App</title>
|
|
140
|
+
<script type="module" src="/@vite/client"></script>
|
|
141
|
+
</head>
|
|
142
|
+
<body>
|
|
143
|
+
<div id="svelte-app">
|
|
144
|
+
${layoutSource ? `<!-- Layout: ${route.layoutPath} -->` : ""}
|
|
145
|
+
<!-- Page: ${route.pagePath} -->
|
|
146
|
+
</div>
|
|
147
|
+
<script type="module" src="${route.pagePath}"></script>
|
|
148
|
+
</body>
|
|
149
|
+
</html>`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Discover all routes in the SvelteKit routes directory.
|
|
154
|
+
*/
|
|
155
|
+
discoverRoutes(): SvelteKitRoute[] {
|
|
156
|
+
const routes: SvelteKitRoute[] = [];
|
|
157
|
+
this.walkRoutes(this.routesDir, "", routes);
|
|
158
|
+
return routes;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private walkRoutes(
|
|
162
|
+
dir: string,
|
|
163
|
+
prefix: string,
|
|
164
|
+
routes: SvelteKitRoute[],
|
|
165
|
+
): void {
|
|
166
|
+
try {
|
|
167
|
+
const entries = this.vfs.readdirSync(dir);
|
|
168
|
+
const hasPage = entries.some(e => e.startsWith("+page."));
|
|
169
|
+
|
|
170
|
+
if (hasPage) {
|
|
171
|
+
routes.push(this.resolvePageRoute(prefix || "/")!);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
if (entry.startsWith("+") || entry.startsWith(".")) continue;
|
|
176
|
+
const full = pathShim.join(dir, entry);
|
|
177
|
+
try {
|
|
178
|
+
if (this.vfs.statSync(full).isDirectory()) {
|
|
179
|
+
this.walkRoutes(full, `${prefix}/${entry}`, routes);
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
/* skip */
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
/* skip */
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private safeRead(path: string): string {
|
|
191
|
+
try {
|
|
192
|
+
return this.vfs.readFileSync(path, "utf8");
|
|
193
|
+
} catch {
|
|
194
|
+
return "";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|