@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.
Files changed (152) hide show
  1. package/dist/browser-bundle.d.ts +40 -0
  2. package/dist/builtins.d.ts +22 -0
  3. package/dist/code-transform.d.ts +7 -0
  4. package/dist/config/cdn.d.ts +13 -0
  5. package/dist/container.d.ts +101 -0
  6. package/dist/dev-server.d.ts +69 -0
  7. package/dist/errors.d.ts +19 -0
  8. package/dist/frameworks/code-transforms.d.ts +32 -0
  9. package/dist/frameworks/next-api-handler.d.ts +72 -0
  10. package/dist/frameworks/next-dev-server.d.ts +141 -0
  11. package/dist/frameworks/next-html-generator.d.ts +36 -0
  12. package/dist/frameworks/next-route-resolver.d.ts +19 -0
  13. package/dist/frameworks/next-shims.d.ts +78 -0
  14. package/dist/frameworks/remix-dev-server.d.ts +47 -0
  15. package/dist/frameworks/sveltekit-dev-server.d.ts +43 -0
  16. package/dist/frameworks/vite-dev-server.d.ts +50 -0
  17. package/dist/fs-errors.d.ts +36 -0
  18. package/dist/index.cjs +14916 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.ts +61 -0
  21. package/dist/index.mjs +14898 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/kernel.d.ts +48 -0
  24. package/dist/memfs.d.ts +144 -0
  25. package/dist/metrics.d.ts +78 -0
  26. package/dist/module-resolver.d.ts +60 -0
  27. package/dist/network-interceptor.d.ts +71 -0
  28. package/dist/npm/cache.d.ts +76 -0
  29. package/dist/npm/index.d.ts +60 -0
  30. package/dist/npm/lockfile-reader.d.ts +32 -0
  31. package/dist/npm/pnpm.d.ts +18 -0
  32. package/dist/npm/registry.d.ts +45 -0
  33. package/dist/npm/resolver.d.ts +39 -0
  34. package/dist/npm/sync-installer.d.ts +18 -0
  35. package/dist/npm/tarball.d.ts +4 -0
  36. package/dist/npm/workspaces.d.ts +46 -0
  37. package/dist/persistence.d.ts +94 -0
  38. package/dist/plugin.d.ts +156 -0
  39. package/dist/polyfills/assert.d.ts +30 -0
  40. package/dist/polyfills/child_process.d.ts +116 -0
  41. package/dist/polyfills/chokidar.d.ts +18 -0
  42. package/dist/polyfills/crypto.d.ts +49 -0
  43. package/dist/polyfills/events.d.ts +28 -0
  44. package/dist/polyfills/fs.d.ts +82 -0
  45. package/dist/polyfills/http.d.ts +147 -0
  46. package/dist/polyfills/module.d.ts +29 -0
  47. package/dist/polyfills/net.d.ts +53 -0
  48. package/dist/polyfills/os.d.ts +91 -0
  49. package/dist/polyfills/path.d.ts +96 -0
  50. package/dist/polyfills/perf_hooks.d.ts +21 -0
  51. package/dist/polyfills/process.d.ts +99 -0
  52. package/dist/polyfills/querystring.d.ts +15 -0
  53. package/dist/polyfills/readdirp.d.ts +18 -0
  54. package/dist/polyfills/readline.d.ts +32 -0
  55. package/dist/polyfills/stream.d.ts +106 -0
  56. package/dist/polyfills/stubs.d.ts +737 -0
  57. package/dist/polyfills/tty.d.ts +25 -0
  58. package/dist/polyfills/url.d.ts +41 -0
  59. package/dist/polyfills/util.d.ts +61 -0
  60. package/dist/polyfills/v8.d.ts +43 -0
  61. package/dist/polyfills/vm.d.ts +76 -0
  62. package/dist/polyfills/worker-threads.d.ts +77 -0
  63. package/dist/polyfills/ws.d.ts +32 -0
  64. package/dist/polyfills/zlib.d.ts +87 -0
  65. package/dist/runtime-helpers.d.ts +4 -0
  66. package/dist/runtime-interface.d.ts +39 -0
  67. package/dist/sandbox.d.ts +69 -0
  68. package/dist/server-bridge.d.ts +55 -0
  69. package/dist/shell-commands.d.ts +2 -0
  70. package/dist/shell.d.ts +101 -0
  71. package/dist/transpiler.d.ts +47 -0
  72. package/dist/type-checker.d.ts +57 -0
  73. package/dist/types/package-json.d.ts +17 -0
  74. package/dist/utils/binary-encoding.d.ts +4 -0
  75. package/dist/utils/hash.d.ts +6 -0
  76. package/dist/utils/safe-path.d.ts +6 -0
  77. package/dist/worker-runtime.d.ts +34 -0
  78. package/package.json +59 -0
  79. package/src/browser-bundle.ts +498 -0
  80. package/src/builtins.ts +222 -0
  81. package/src/code-transform.ts +183 -0
  82. package/src/config/cdn.ts +17 -0
  83. package/src/container.ts +343 -0
  84. package/src/dev-server.ts +322 -0
  85. package/src/errors.ts +604 -0
  86. package/src/frameworks/code-transforms.ts +667 -0
  87. package/src/frameworks/next-api-handler.ts +366 -0
  88. package/src/frameworks/next-dev-server.ts +1252 -0
  89. package/src/frameworks/next-html-generator.ts +585 -0
  90. package/src/frameworks/next-route-resolver.ts +521 -0
  91. package/src/frameworks/next-shims.ts +1084 -0
  92. package/src/frameworks/remix-dev-server.ts +163 -0
  93. package/src/frameworks/sveltekit-dev-server.ts +197 -0
  94. package/src/frameworks/vite-dev-server.ts +370 -0
  95. package/src/fs-errors.ts +118 -0
  96. package/src/index.ts +188 -0
  97. package/src/kernel.ts +381 -0
  98. package/src/memfs.ts +1006 -0
  99. package/src/metrics.ts +140 -0
  100. package/src/module-resolver.ts +511 -0
  101. package/src/network-interceptor.ts +143 -0
  102. package/src/npm/cache.ts +172 -0
  103. package/src/npm/index.ts +377 -0
  104. package/src/npm/lockfile-reader.ts +105 -0
  105. package/src/npm/pnpm.ts +108 -0
  106. package/src/npm/registry.ts +120 -0
  107. package/src/npm/resolver.ts +339 -0
  108. package/src/npm/sync-installer.ts +217 -0
  109. package/src/npm/tarball.ts +136 -0
  110. package/src/npm/workspaces.ts +255 -0
  111. package/src/persistence.ts +235 -0
  112. package/src/plugin.ts +293 -0
  113. package/src/polyfills/assert.ts +164 -0
  114. package/src/polyfills/child_process.ts +535 -0
  115. package/src/polyfills/chokidar.ts +52 -0
  116. package/src/polyfills/crypto.ts +433 -0
  117. package/src/polyfills/events.ts +178 -0
  118. package/src/polyfills/fs.ts +297 -0
  119. package/src/polyfills/http.ts +478 -0
  120. package/src/polyfills/module.ts +97 -0
  121. package/src/polyfills/net.ts +123 -0
  122. package/src/polyfills/os.ts +108 -0
  123. package/src/polyfills/path.ts +169 -0
  124. package/src/polyfills/perf_hooks.ts +30 -0
  125. package/src/polyfills/process.ts +349 -0
  126. package/src/polyfills/querystring.ts +66 -0
  127. package/src/polyfills/readdirp.ts +72 -0
  128. package/src/polyfills/readline.ts +80 -0
  129. package/src/polyfills/stream.ts +610 -0
  130. package/src/polyfills/stubs.ts +600 -0
  131. package/src/polyfills/tty.ts +43 -0
  132. package/src/polyfills/url.ts +97 -0
  133. package/src/polyfills/util.ts +173 -0
  134. package/src/polyfills/v8.ts +62 -0
  135. package/src/polyfills/vm.ts +111 -0
  136. package/src/polyfills/worker-threads.ts +189 -0
  137. package/src/polyfills/ws.ts +73 -0
  138. package/src/polyfills/zlib.ts +244 -0
  139. package/src/runtime-helpers.ts +83 -0
  140. package/src/runtime-interface.ts +46 -0
  141. package/src/sandbox.ts +178 -0
  142. package/src/server-bridge.ts +473 -0
  143. package/src/service-worker.ts +153 -0
  144. package/src/shell-commands.ts +708 -0
  145. package/src/shell.ts +795 -0
  146. package/src/transpiler.ts +282 -0
  147. package/src/type-checker.ts +241 -0
  148. package/src/types/package-json.ts +17 -0
  149. package/src/utils/binary-encoding.ts +38 -0
  150. package/src/utils/hash.ts +24 -0
  151. package/src/utils/safe-path.ts +38 -0
  152. package/src/worker-runtime.ts +42 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Vite-compatible dev server for jiki.
3
+ *
4
+ * Serves files as ES modules with on-the-fly esbuild-wasm transpilation.
5
+ * Supports React, Vue, Svelte, and any Vite-compatible framework by
6
+ * transforming files before serving.
7
+ *
8
+ * Features:
9
+ * - ESM-based module serving (no bundling, fast per-module transforms)
10
+ * - `/@modules/<pkg>` for bare import resolution from node_modules
11
+ * - CSS → JS module injection (injects `<style>` tags at runtime)
12
+ * - HMR update emission on file changes
13
+ * - HTML generation with module script tags
14
+ */
15
+
16
+ import {
17
+ DevServer,
18
+ type DevServerOptions,
19
+ type ResponseData,
20
+ type HMRUpdate,
21
+ } from "../dev-server";
22
+ import { MemFS } from "../memfs";
23
+ import { BufferImpl as Buffer } from "../polyfills/stream";
24
+ import * as pathShim from "../polyfills/path";
25
+ import { processSource, transformEsmToCjs } from "../code-transform";
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Options
29
+ // ---------------------------------------------------------------------------
30
+
31
+ export interface ViteDevServerOptions extends DevServerOptions {
32
+ /** Entry HTML file (default: `/index.html`). */
33
+ entry?: string;
34
+ /** Framework preset for transform hints. */
35
+ framework?: "react" | "vue" | "svelte" | "solid" | "vanilla";
36
+ /** JSX import source (default: `react` for react, `solid-js` for solid). */
37
+ jsxImportSource?: string;
38
+ }
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // ViteDevServer
42
+ // ---------------------------------------------------------------------------
43
+
44
+ export class ViteDevServer extends DevServer {
45
+ private entry: string;
46
+ private framework: string;
47
+ private jsxImportSource: string;
48
+
49
+ constructor(vfs: MemFS, options: ViteDevServerOptions) {
50
+ super(vfs, options);
51
+ this.entry = options.entry || "/index.html";
52
+ this.framework = options.framework || "react";
53
+ this.jsxImportSource =
54
+ options.jsxImportSource ||
55
+ (this.framework === "solid" ? "solid-js" : "react");
56
+ }
57
+
58
+ async handleRequest(
59
+ method: string,
60
+ url: string,
61
+ headers: Record<string, string>,
62
+ body?: Buffer,
63
+ ): Promise<ResponseData> {
64
+ if (method === "OPTIONS") return this.handleOptionsRequest();
65
+
66
+ const parsed = new URL(url, "http://localhost");
67
+ const pathname = decodeURIComponent(parsed.pathname);
68
+
69
+ // Serve HMR client
70
+ if (pathname === "/@vite/client") {
71
+ return this.addCorsHeaders(this.serveHmrClient());
72
+ }
73
+
74
+ // Resolve bare imports: /@modules/react → node_modules/react
75
+ if (pathname.startsWith("/@modules/")) {
76
+ const pkgPath = pathname.slice("/@modules/".length);
77
+ return this.addCorsHeaders(await this.serveBareImport(pkgPath));
78
+ }
79
+
80
+ // Serve HTML
81
+ if (pathname === "/" || pathname.endsWith(".html")) {
82
+ const htmlPath =
83
+ pathname === "/" ? this.entry : pathShim.join(this.root, pathname);
84
+ return this.addCorsHeaders(this.serveHtml(htmlPath));
85
+ }
86
+
87
+ // Serve and transform JS/TS/JSX/TSX
88
+ if (this.isTransformable(pathname)) {
89
+ return this.addCorsHeaders(await this.serveTransformed(pathname));
90
+ }
91
+
92
+ // Serve CSS as JS module
93
+ if (pathname.endsWith(".css")) {
94
+ return this.addCorsHeaders(this.serveCssAsModule(pathname));
95
+ }
96
+
97
+ // Serve static files as-is
98
+ return this.addCorsHeaders(this.serveFile(pathname));
99
+ }
100
+
101
+ startWatching(): void {
102
+ this.vfs.on("change", (path: string) => {
103
+ if (this.isTransformable(path) || path.endsWith(".css")) {
104
+ this.broadcastChange({
105
+ type: "update",
106
+ path,
107
+ timestamp: Date.now(),
108
+ });
109
+ } else if (path.endsWith(".html")) {
110
+ this.broadcastChange({
111
+ type: "full-reload",
112
+ path,
113
+ timestamp: Date.now(),
114
+ });
115
+ }
116
+ });
117
+ }
118
+
119
+ // -- HTML serving ---------------------------------------------------------
120
+
121
+ private serveHtml(htmlPath: string): ResponseData {
122
+ const resolved = this.resolvePath(htmlPath);
123
+ try {
124
+ let html = this.vfs.readFileSync(resolved, "utf8");
125
+ // Inject HMR client script
126
+ html = html.replace(
127
+ "</head>",
128
+ `<script type="module" src="/@vite/client"></script>\n</head>`,
129
+ );
130
+ const buf = Buffer.from(html);
131
+ return {
132
+ statusCode: 200,
133
+ statusMessage: "OK",
134
+ headers: {
135
+ "Content-Type": "text/html; charset=utf-8",
136
+ "Content-Length": String(buf.length),
137
+ "Cache-Control": "no-cache",
138
+ },
139
+ body: buf,
140
+ };
141
+ } catch {
142
+ // If no index.html, generate a minimal one
143
+ return this.generateDefaultHtml();
144
+ }
145
+ }
146
+
147
+ private generateDefaultHtml(): ResponseData {
148
+ const html = `<!DOCTYPE html>
149
+ <html>
150
+ <head>
151
+ <meta charset="utf-8" />
152
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
153
+ <title>Vite App</title>
154
+ <script type="module" src="/@vite/client"></script>
155
+ </head>
156
+ <body>
157
+ <div id="root"></div>
158
+ <div id="app"></div>
159
+ <script type="module" src="/src/main.tsx"></script>
160
+ <script type="module" src="/src/main.ts"></script>
161
+ <script type="module" src="/src/main.jsx"></script>
162
+ <script type="module" src="/src/main.js"></script>
163
+ </body>
164
+ </html>`;
165
+ const buf = Buffer.from(html);
166
+ return {
167
+ statusCode: 200,
168
+ statusMessage: "OK",
169
+ headers: {
170
+ "Content-Type": "text/html; charset=utf-8",
171
+ "Content-Length": String(buf.length),
172
+ "Cache-Control": "no-cache",
173
+ },
174
+ body: buf,
175
+ };
176
+ }
177
+
178
+ // -- Module transforms ----------------------------------------------------
179
+
180
+ private isTransformable(path: string): boolean {
181
+ return /\.(js|ts|tsx|jsx|mjs|cjs)$/.test(path);
182
+ }
183
+
184
+ private async serveTransformed(pathname: string): Promise<ResponseData> {
185
+ const filePath = this.resolvePath(pathname);
186
+ try {
187
+ const source = this.vfs.readFileSync(filePath, "utf8");
188
+ let code = this.transformModule(source, filePath);
189
+ // Rewrite bare imports to /@modules/ prefix
190
+ code = this.rewriteBareImports(code);
191
+ // Rewrite relative CSS imports to request path
192
+ code = this.rewriteCssImports(code, pathname);
193
+
194
+ const buf = Buffer.from(code);
195
+ return {
196
+ statusCode: 200,
197
+ statusMessage: "OK",
198
+ headers: {
199
+ "Content-Type": "application/javascript; charset=utf-8",
200
+ "Content-Length": String(buf.length),
201
+ "Cache-Control": "no-cache",
202
+ },
203
+ body: buf,
204
+ };
205
+ } catch (err) {
206
+ return this.serverError(err);
207
+ }
208
+ }
209
+
210
+ private transformModule(source: string, filePath: string): string {
211
+ try {
212
+ return processSource(source, filePath);
213
+ } catch {
214
+ // If processSource fails (e.g. transpiler not initialised),
215
+ // return the source with basic ESM-to-CJS conversion
216
+ try {
217
+ return transformEsmToCjs(source, filePath);
218
+ } catch {
219
+ return source;
220
+ }
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Rewrite bare import specifiers to /@modules/ URLs.
226
+ * e.g. `import React from "react"` → `import React from "/@modules/react"`
227
+ */
228
+ private rewriteBareImports(code: string): string {
229
+ // Match: require("pkg"), require("@scope/pkg"), require("pkg/sub")
230
+ return code.replace(
231
+ /require\(["']([^./][^"']*)["']\)/g,
232
+ (match, specifier) => {
233
+ // Skip node: builtins
234
+ if (specifier.startsWith("node:")) return match;
235
+ return `require("/@modules/${specifier}")`;
236
+ },
237
+ );
238
+ }
239
+
240
+ /**
241
+ * Rewrite CSS imports to use absolute paths.
242
+ */
243
+ private rewriteCssImports(code: string, fromPath: string): string {
244
+ const dir = pathShim.dirname(fromPath);
245
+ return code.replace(
246
+ /require\(["'](\.\.?\/[^"']*\.css)["']\)/g,
247
+ (_match, relPath) => {
248
+ const abs = pathShim.resolve(dir, relPath);
249
+ return `require("${abs}")`;
250
+ },
251
+ );
252
+ }
253
+
254
+ // -- CSS as JS module -----------------------------------------------------
255
+
256
+ private serveCssAsModule(pathname: string): ResponseData {
257
+ const filePath = this.resolvePath(pathname);
258
+ try {
259
+ const css = this.vfs.readFileSync(filePath, "utf8");
260
+ // Wrap CSS in a JS module that injects a <style> tag
261
+ const escaped = css
262
+ .replace(/\\/g, "\\\\")
263
+ .replace(/`/g, "\\`")
264
+ .replace(/\$/g, "\\$");
265
+ const code = [
266
+ `const css = \`${escaped}\`;`,
267
+ `if (typeof document !== 'undefined') {`,
268
+ ` const style = document.createElement('style');`,
269
+ ` style.setAttribute('data-vite-css', '${pathname}');`,
270
+ ` style.textContent = css;`,
271
+ ` document.head.appendChild(style);`,
272
+ `}`,
273
+ `module.exports = {};`,
274
+ ].join("\n");
275
+
276
+ const buf = Buffer.from(code);
277
+ return {
278
+ statusCode: 200,
279
+ statusMessage: "OK",
280
+ headers: {
281
+ "Content-Type": "application/javascript; charset=utf-8",
282
+ "Content-Length": String(buf.length),
283
+ "Cache-Control": "no-cache",
284
+ },
285
+ body: buf,
286
+ };
287
+ } catch {
288
+ return this.notFound(pathname);
289
+ }
290
+ }
291
+
292
+ // -- Bare import resolution -----------------------------------------------
293
+
294
+ private async serveBareImport(pkgPath: string): Promise<ResponseData> {
295
+ // Resolve from node_modules
296
+ const nmPath = pathShim.join(this.root, "node_modules", pkgPath);
297
+
298
+ // Check if it's a direct file
299
+ if (this.exists(nmPath) && !this.isDirectory(nmPath)) {
300
+ return this.serveTransformed(`/node_modules/${pkgPath}`);
301
+ }
302
+
303
+ // Try to resolve via package.json main/module/exports
304
+ const pkgJsonPath = pathShim.join(nmPath, "package.json");
305
+ if (this.exists(pkgJsonPath)) {
306
+ try {
307
+ const pkg = JSON.parse(this.vfs.readFileSync(pkgJsonPath, "utf8"));
308
+ const entry = pkg.module || pkg.main || "index.js";
309
+ const entryPath = pathShim.join(nmPath, entry);
310
+ if (this.exists(entryPath)) {
311
+ return this.serveTransformed(`/node_modules/${pkgPath}/${entry}`);
312
+ }
313
+ } catch {}
314
+ }
315
+
316
+ // Try common index files
317
+ for (const idx of ["index.js", "index.mjs", "index.ts"]) {
318
+ const idxPath = pathShim.join(nmPath, idx);
319
+ if (this.exists(idxPath)) {
320
+ return this.serveTransformed(`/node_modules/${pkgPath}/${idx}`);
321
+ }
322
+ }
323
+
324
+ return this.notFound(`/@modules/${pkgPath}`);
325
+ }
326
+
327
+ // -- HMR client -----------------------------------------------------------
328
+
329
+ private serveHmrClient(): ResponseData {
330
+ const code = `
331
+ // Minimal Vite HMR client for jiki
332
+ const listeners = new Map();
333
+
334
+ export function createHotContext(ownerPath) {
335
+ return {
336
+ accept(deps, callback) {
337
+ if (typeof deps === 'function') {
338
+ listeners.set(ownerPath, deps);
339
+ } else if (callback) {
340
+ listeners.set(ownerPath, callback);
341
+ }
342
+ },
343
+ dispose(cb) {},
344
+ prune(cb) {},
345
+ decline() {},
346
+ invalidate() {},
347
+ on(event, cb) {},
348
+ };
349
+ }
350
+
351
+ export const hot = createHotContext('/');
352
+
353
+ // import.meta.hot compatibility
354
+ if (typeof window !== 'undefined') {
355
+ window.__vite_hot__ = { createHotContext, listeners };
356
+ }
357
+ `;
358
+ const buf = Buffer.from(code);
359
+ return {
360
+ statusCode: 200,
361
+ statusMessage: "OK",
362
+ headers: {
363
+ "Content-Type": "application/javascript; charset=utf-8",
364
+ "Content-Length": String(buf.length),
365
+ "Cache-Control": "no-cache",
366
+ },
367
+ body: buf,
368
+ };
369
+ }
370
+ }
@@ -0,0 +1,118 @@
1
+ export interface NodeError extends Error {
2
+ code: string;
3
+ errno: number;
4
+ syscall: string;
5
+ path?: string;
6
+ }
7
+
8
+ export type ErrorCode =
9
+ | "ENOENT"
10
+ | "ENOTDIR"
11
+ | "EISDIR"
12
+ | "EEXIST"
13
+ | "ENOTEMPTY"
14
+ | "ELOOP"
15
+ | "EINVAL"
16
+ | "EPERM";
17
+
18
+ const ERRORS: Record<string, { errno: number; text: string }> = {
19
+ ENOENT: { errno: -2, text: "no such file or directory" },
20
+ ENOTDIR: { errno: -20, text: "not a directory" },
21
+ EISDIR: { errno: -21, text: "is a directory" },
22
+ EEXIST: { errno: -17, text: "file already exists" },
23
+ ENOTEMPTY: { errno: -39, text: "directory not empty" },
24
+ ELOOP: { errno: -40, text: "too many levels of symbolic links" },
25
+ EINVAL: { errno: -22, text: "invalid argument" },
26
+ EPERM: { errno: -1, text: "operation not permitted" },
27
+ };
28
+
29
+ export function createNodeError(
30
+ code: ErrorCode,
31
+ syscall: string,
32
+ path: string,
33
+ message?: string,
34
+ ): NodeError {
35
+ const info = ERRORS[code];
36
+ const e = new Error(
37
+ message || `[${code}] ${syscall}: ${info.text} (${path})`,
38
+ ) as NodeError;
39
+ e.code = code;
40
+ e.errno = info.errno;
41
+ e.syscall = syscall;
42
+ e.path = path;
43
+ return e;
44
+ }
45
+
46
+ export interface Stats {
47
+ isFile(): boolean;
48
+ isDirectory(): boolean;
49
+ isSymbolicLink(): boolean;
50
+ isBlockDevice(): boolean;
51
+ isCharacterDevice(): boolean;
52
+ isFIFO(): boolean;
53
+ isSocket(): boolean;
54
+ size: number;
55
+ mode: number;
56
+ mtime: Date;
57
+ atime: Date;
58
+ ctime: Date;
59
+ birthtime: Date;
60
+ mtimeMs: number;
61
+ atimeMs: number;
62
+ ctimeMs: number;
63
+ birthtimeMs: number;
64
+ nlink: number;
65
+ uid: number;
66
+ gid: number;
67
+ dev: number;
68
+ ino: number;
69
+ rdev: number;
70
+ blksize: number;
71
+ blocks: number;
72
+ }
73
+
74
+ let inoSeq = 1;
75
+
76
+ function modeForType(type: "file" | "directory" | "symlink"): number {
77
+ if (type === "directory") return 0o755;
78
+ if (type === "symlink") return 0o777;
79
+ return 0o644;
80
+ }
81
+
82
+ export function buildStats(
83
+ type: "file" | "directory" | "symlink",
84
+ size: number,
85
+ mtime: number,
86
+ ino?: number,
87
+ ): Stats {
88
+ const ts = mtime;
89
+ const id = ino ?? inoSeq++;
90
+ const m = modeForType(type);
91
+ return {
92
+ isFile: () => type === "file",
93
+ isDirectory: () => type === "directory",
94
+ isSymbolicLink: () => type === "symlink",
95
+ isBlockDevice: () => false,
96
+ isCharacterDevice: () => false,
97
+ isFIFO: () => false,
98
+ isSocket: () => false,
99
+ size,
100
+ mode: m,
101
+ mtime: new Date(ts),
102
+ atime: new Date(ts),
103
+ ctime: new Date(ts),
104
+ birthtime: new Date(ts),
105
+ mtimeMs: ts,
106
+ atimeMs: ts,
107
+ ctimeMs: ts,
108
+ birthtimeMs: ts,
109
+ nlink: 1,
110
+ uid: 1000,
111
+ gid: 1000,
112
+ dev: 0,
113
+ ino: id,
114
+ rdev: 0,
115
+ blksize: 4096,
116
+ blocks: Math.ceil(size / 512),
117
+ };
118
+ }
package/src/index.ts ADDED
@@ -0,0 +1,188 @@
1
+ // jiki - Lightweight browser-based Node.js runtime (MIT)
2
+
3
+ export { MemFS } from "./memfs";
4
+ export { MemFS as VirtualFS } from "./memfs";
5
+ export type {
6
+ FSNode,
7
+ Stats,
8
+ WatchEventType,
9
+ WatchListener,
10
+ FSWatcher,
11
+ NodeError,
12
+ } from "./memfs";
13
+ export { createNodeError } from "./memfs";
14
+
15
+ export { Kernel, Runtime } from "./kernel";
16
+ export type { Module, RuntimeOptions, RequireFunction } from "./kernel";
17
+ export type { AutoInstallProvider } from "./module-resolver";
18
+ export type {
19
+ IRuntime,
20
+ IExecuteResult,
21
+ IRuntimeOptions,
22
+ VFSSnapshot,
23
+ VFSFileEntry,
24
+ } from "./runtime-interface";
25
+
26
+ export { Container, boot, createContainer, registerPlugin } from "./container";
27
+ export type { ContainerOptions, RunResult } from "./container";
28
+
29
+ export {
30
+ registerBuiltin,
31
+ registerBuiltins,
32
+ unregisterBuiltin,
33
+ listBuiltins,
34
+ } from "./builtins";
35
+
36
+ export { PluginRegistry } from "./plugin";
37
+
38
+ export { IndexedDBAdapter, InMemoryAdapter } from "./persistence";
39
+ export type {
40
+ PersistenceAdapter,
41
+ PersistedEntry,
42
+ IndexedDBAdapterOptions,
43
+ } from "./persistence";
44
+ export type { MemFSOptions } from "./memfs";
45
+ export type {
46
+ JikiPlugin,
47
+ PluginHooks,
48
+ OnResolveArgs,
49
+ OnResolveResult,
50
+ OnResolveCallback,
51
+ OnLoadArgs,
52
+ OnLoadResult,
53
+ OnLoadCallback,
54
+ OnTransformArgs,
55
+ OnTransformResult,
56
+ OnTransformCallback,
57
+ OnInstallCallback,
58
+ OnBootCallback,
59
+ } from "./plugin";
60
+
61
+ export { PackageManager, NpmLayout } from "./npm/index";
62
+ export type {
63
+ LayoutStrategy,
64
+ InstallOptions,
65
+ InstallResult,
66
+ } from "./npm/index";
67
+ export { PnpmLayout } from "./npm/pnpm";
68
+
69
+ export { PackageCache } from "./npm/cache";
70
+ export type { PackageCacheOptions } from "./npm/cache";
71
+
72
+ export { shouldUseWorker } from "./worker-runtime";
73
+ export type { WorkerMode, WorkerRuntimeConfig } from "./worker-runtime";
74
+
75
+ export { SandboxGuard } from "./sandbox";
76
+ export type {
77
+ SandboxOptions,
78
+ SandboxLimits,
79
+ SandboxNetwork,
80
+ SandboxFs,
81
+ } from "./sandbox";
82
+
83
+ export { Metrics } from "./metrics";
84
+ export type { MetricsSnapshot } from "./metrics";
85
+
86
+ export {
87
+ NetworkInterceptor,
88
+ mockResponseToFetchResponse,
89
+ } from "./network-interceptor";
90
+ export type { MockResponse, FetchHandler } from "./network-interceptor";
91
+
92
+ export {
93
+ discoverWorkspaces,
94
+ resolveWorkspaceDep,
95
+ isWorkspaceProtocol,
96
+ linkWorkspaces,
97
+ } from "./npm/workspaces";
98
+ export type { WorkspacePackage } from "./npm/workspaces";
99
+
100
+ export { TypeChecker } from "./type-checker";
101
+ export type { Diagnostic, TypeCheckerOptions } from "./type-checker";
102
+
103
+ export {
104
+ Worker as WorkerThread,
105
+ MessageChannel,
106
+ MessagePort,
107
+ } from "./polyfills/worker-threads";
108
+
109
+ export { Shell, ShellHistory, createShell } from "./shell";
110
+ export type {
111
+ ShellOptions,
112
+ ShellProcess,
113
+ ShellContext,
114
+ CommandHandler,
115
+ ShellResult,
116
+ } from "./shell";
117
+
118
+ export {
119
+ initTranspiler,
120
+ transpile,
121
+ transpileSync,
122
+ bundle,
123
+ stopTranspiler,
124
+ needsTranspilation,
125
+ setWasmURL,
126
+ hasSyncSupport,
127
+ } from "./transpiler";
128
+ export type {
129
+ TranspileOptions,
130
+ BundleOptions,
131
+ BundleResult,
132
+ InitOptions,
133
+ } from "./transpiler";
134
+
135
+ export { NextDevServer } from "./frameworks/next-dev-server";
136
+ export type { NextDevServerOptions } from "./frameworks/next-dev-server";
137
+ export { ViteDevServer } from "./frameworks/vite-dev-server";
138
+ export type { ViteDevServerOptions } from "./frameworks/vite-dev-server";
139
+ export { SvelteKitDevServer } from "./frameworks/sveltekit-dev-server";
140
+ export type { SvelteKitDevServerOptions } from "./frameworks/sveltekit-dev-server";
141
+ export { RemixDevServer } from "./frameworks/remix-dev-server";
142
+ export type {
143
+ RemixDevServerOptions,
144
+ RemixRoute,
145
+ } from "./frameworks/remix-dev-server";
146
+ export { DevServer } from "./dev-server";
147
+ export type { DevServerOptions, HMRUpdate, ResponseData } from "./dev-server";
148
+
149
+ export {
150
+ ServerBridge,
151
+ getServerBridge,
152
+ resetServerBridge,
153
+ } from "./server-bridge";
154
+ export type {
155
+ IVirtualServer,
156
+ VirtualServer,
157
+ BridgeOptions,
158
+ InitServiceWorkerOptions,
159
+ } from "./server-bridge";
160
+
161
+ export {
162
+ setServerListenCallback,
163
+ setServerCloseCallback,
164
+ } from "./polyfills/http";
165
+
166
+ export {
167
+ bundlePackageForBrowser,
168
+ generateRequireScript,
169
+ scanBareImports,
170
+ preprocessImports,
171
+ extractPackageName,
172
+ } from "./browser-bundle";
173
+ export type { BrowserBundle, BundleError } from "./browser-bundle";
174
+
175
+ export {
176
+ parseError,
177
+ formatErrorText,
178
+ formatErrorHtml,
179
+ errorOverlayScript,
180
+ } from "./errors";
181
+ export type { ContainerError, ErrorCategory } from "./errors";
182
+
183
+ export * as pathShim from "./polyfills/path";
184
+ export { EventEmitter } from "./polyfills/events";
185
+ export { createProcess } from "./polyfills/process";
186
+ export type { Process, ProcessEnv } from "./polyfills/process";
187
+ export { createFsShim } from "./polyfills/fs";
188
+ export type { FsShim } from "./polyfills/fs";