rari 0.1.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.
@@ -0,0 +1,69 @@
1
+ import { Route, RouteGenerationOptions } from "./runtime-client-BEWMJWMx.js";
2
+ import { Plugin, UserConfig } from "rolldown-vite";
3
+
4
+ //#region src/router/file-routes.d.ts
5
+ declare class FileRouteGenerator {
6
+ private pagesDir;
7
+ private extensions;
8
+ private routes;
9
+ private routeTree;
10
+ constructor(options: RouteGenerationOptions);
11
+ generateRoutes(): Promise<Route[]>;
12
+ private scanPagesDirectory;
13
+ private scanDirectory;
14
+ private shouldSkipDirectory;
15
+ private shouldSkipFile;
16
+ private processFiles;
17
+ private fileToRoute;
18
+ private buildRouteTree;
19
+ private insertRouteIntoTree;
20
+ private applyLayoutToTree;
21
+ private establishParentChildRelations;
22
+ private flattenRouteTree;
23
+ getRoutes(): Route[];
24
+ getRouteByPath(path: string): Route | undefined;
25
+ getRouteByFilePath(filePath: string): Route | undefined;
26
+ refresh(): Promise<Route[]>;
27
+ }
28
+ declare function generateFileRoutes(options: RouteGenerationOptions): Promise<Route[]>;
29
+ declare function watchFileRoutes(options: RouteGenerationOptions, onChange: (routes: Route[]) => void): () => void;
30
+ declare function createRouteManifest(routes: Route[], outputPath: string): Promise<void>;
31
+ declare function loadRouteManifest(manifestPath: string): Promise<Route[]>;
32
+ declare function validateRoutes(routes: Route[]): {
33
+ valid: boolean;
34
+ errors: string[];
35
+ };
36
+ declare function convertFilePatternToRoutePattern(pattern: string): string;
37
+ //#endregion
38
+ //#region src/router/vite-plugin.d.ts
39
+ interface RariRouterPluginOptions {
40
+ pagesDir?: string;
41
+ extensions?: string[];
42
+ outDir?: string;
43
+ generateTypes?: boolean;
44
+ validate?: boolean;
45
+ dev?: boolean;
46
+ transforms?: Array<(route: Route) => Route>;
47
+ }
48
+ declare function rariRouter(options?: RariRouterPluginOptions): Plugin;
49
+ //#endregion
50
+ //#region src/vite/server-build.d.ts
51
+ interface ServerBuildOptions {
52
+ outDir?: string;
53
+ serverDir?: string;
54
+ manifestPath?: string;
55
+ minify?: boolean;
56
+ }
57
+ //#endregion
58
+ //#region src/vite/index.d.ts
59
+ interface RariOptions {
60
+ projectRoot?: string;
61
+ serverBuild?: ServerBuildOptions;
62
+ serverHandler?: boolean;
63
+ }
64
+ declare function rari(options?: RariOptions): Plugin[];
65
+ declare function defineRariConfig(config: UserConfig & {
66
+ plugins?: Plugin[];
67
+ }): UserConfig;
68
+ //#endregion
69
+ export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
@@ -0,0 +1,3 @@
1
+ import { ServerComponentBuilder, createServerBuildPlugin, scanDirectory } from "./server-build-DaBgiV55.js";
2
+
3
+ export { ServerComponentBuilder, scanDirectory };
@@ -0,0 +1,618 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { build } from "esbuild";
5
+
6
+ //#region src/vite/server-build.ts
7
+ var ServerComponentBuilder = class {
8
+ serverComponents = /* @__PURE__ */ new Map();
9
+ options;
10
+ projectRoot;
11
+ getComponentCount() {
12
+ return this.serverComponents.size;
13
+ }
14
+ constructor(projectRoot, options = {}) {
15
+ this.projectRoot = projectRoot;
16
+ this.options = {
17
+ outDir: options.outDir || path.join(projectRoot, "dist"),
18
+ serverDir: options.serverDir || "server",
19
+ manifestPath: options.manifestPath || "server-manifest.json",
20
+ minify: options.minify ?? process.env.NODE_ENV === "production"
21
+ };
22
+ }
23
+ isServerComponent(filePath) {
24
+ try {
25
+ if (!fs.existsSync(filePath)) return false;
26
+ const code = fs.readFileSync(filePath, "utf-8");
27
+ const serverDirectives = [
28
+ "'use server'",
29
+ "\"use server\"",
30
+ "/* @server */",
31
+ "// @server"
32
+ ];
33
+ const trimmedCode = code.trim();
34
+ const hasServerDirective = serverDirectives.some((directive) => trimmedCode.startsWith(directive) || code.includes(directive));
35
+ const isInFunctionsDir = filePath.includes("/functions/") || filePath.includes("\\functions\\");
36
+ const hasServerFunctionSignature = (code.includes("export async function") || code.includes("export function")) && code.includes("'use server'");
37
+ const hasNodeImports = code.includes("from 'node:") || code.includes("from \"node:") || code.includes("from 'fs'") || code.includes("from \"fs\"") || code.includes("from 'path'") || code.includes("from \"path\"");
38
+ const hasAsyncDefaultExport = /export\s+default\s+async\s+function/.test(code);
39
+ const isServer = hasServerDirective || isInFunctionsDir && hasServerFunctionSignature || hasNodeImports && hasAsyncDefaultExport;
40
+ return isServer;
41
+ } catch {
42
+ return false;
43
+ }
44
+ }
45
+ isClientComponent(filePath) {
46
+ try {
47
+ if (!fs.existsSync(filePath)) return false;
48
+ const code = fs.readFileSync(filePath, "utf-8");
49
+ const clientDirectives = [
50
+ "'use client'",
51
+ "\"use client\"",
52
+ "/* @client */",
53
+ "// @client"
54
+ ];
55
+ const trimmedCode = code.trim();
56
+ const hasClientDirective = clientDirectives.some((directive) => trimmedCode.startsWith(directive) || code.includes(directive));
57
+ return hasClientDirective;
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ addServerComponent(filePath) {
63
+ if (!this.isServerComponent(filePath)) return;
64
+ const code = fs.readFileSync(filePath, "utf-8");
65
+ const dependencies = this.extractDependencies(code);
66
+ const hasNodeImports = this.hasNodeImports(code);
67
+ this.serverComponents.set(filePath, {
68
+ filePath,
69
+ originalCode: code,
70
+ dependencies,
71
+ hasNodeImports
72
+ });
73
+ }
74
+ extractDependencies(code) {
75
+ const dependencies = [];
76
+ const importRegex = /import(?:\s+(?:\w+|\{[^}]*\}|\*\s+as\s+\w+)(?:\s*,\s*(?:\w+|\{[^}]*\}|\*\s+as\s+\w+))*\s+from\s+)?['"]([^'"]+)['"]/g;
77
+ let match;
78
+ while (true) {
79
+ match = importRegex.exec(code);
80
+ if (match === null) break;
81
+ const importPath = match[1];
82
+ if (!importPath.startsWith(".") && !importPath.startsWith("/") && !importPath.startsWith("node:") && !this.isNodeBuiltin(importPath)) dependencies.push(importPath);
83
+ }
84
+ return Array.from(new Set(dependencies));
85
+ }
86
+ isNodeBuiltin(moduleName) {
87
+ const nodeBuiltins = [
88
+ "fs",
89
+ "path",
90
+ "os",
91
+ "crypto",
92
+ "util",
93
+ "stream",
94
+ "events",
95
+ "process",
96
+ "buffer",
97
+ "url",
98
+ "querystring",
99
+ "zlib",
100
+ "http",
101
+ "https",
102
+ "net",
103
+ "tls",
104
+ "child_process",
105
+ "cluster",
106
+ "worker_threads"
107
+ ];
108
+ return nodeBuiltins.includes(moduleName);
109
+ }
110
+ hasNodeImports(code) {
111
+ return code.includes("from 'node:") || code.includes("from \"node:") || code.includes("from 'fs'") || code.includes("from \"fs\"") || code.includes("from 'path'") || code.includes("from \"path\"") || code.includes("from 'os'") || code.includes("from \"os\"") || code.includes("from 'crypto'") || code.includes("from \"crypto\"") || code.includes("from 'util'") || code.includes("from \"util\"") || code.includes("from 'stream'") || code.includes("from \"stream\"") || code.includes("from 'events'") || code.includes("from \"events\"");
112
+ }
113
+ async getTransformedComponentsForDevelopment() {
114
+ const components = [];
115
+ for (const [filePath, component] of this.serverComponents) {
116
+ const relativePath = path.relative(this.projectRoot, filePath);
117
+ const componentId = this.getComponentId(relativePath);
118
+ const transformedCode = await this.buildComponentCodeOnly(filePath, componentId, component);
119
+ components.push({
120
+ id: componentId,
121
+ code: transformedCode
122
+ });
123
+ }
124
+ return components;
125
+ }
126
+ async buildComponentCodeOnly(inputPath, componentId, _component) {
127
+ const originalCode = await fs.promises.readFile(inputPath, "utf-8");
128
+ const clientTransformedCode = this.transformClientImports(originalCode, inputPath);
129
+ const transformedCode = this.transformNodeImports(clientTransformedCode);
130
+ const ext = path.extname(inputPath);
131
+ let loader;
132
+ if (ext === ".tsx") loader = "tsx";
133
+ else if (ext === ".ts") loader = "ts";
134
+ else if (ext === ".jsx") loader = "jsx";
135
+ else loader = "js";
136
+ try {
137
+ const result = await build({
138
+ stdin: {
139
+ contents: transformedCode,
140
+ resolveDir: path.dirname(inputPath),
141
+ sourcefile: inputPath,
142
+ loader
143
+ },
144
+ bundle: true,
145
+ platform: "neutral",
146
+ target: "es2022",
147
+ format: "esm",
148
+ external: [],
149
+ mainFields: ["module", "main"],
150
+ conditions: [
151
+ "import",
152
+ "module",
153
+ "default"
154
+ ],
155
+ define: {
156
+ "global": "globalThis",
157
+ "process.env.NODE_ENV": "\"production\""
158
+ },
159
+ loader: {
160
+ ".ts": "ts",
161
+ ".tsx": "tsx",
162
+ ".js": "js",
163
+ ".jsx": "jsx"
164
+ },
165
+ resolveExtensions: [
166
+ ".ts",
167
+ ".tsx",
168
+ ".js",
169
+ ".jsx"
170
+ ],
171
+ minify: false,
172
+ minifyIdentifiers: false,
173
+ sourcemap: false,
174
+ metafile: false,
175
+ write: false,
176
+ plugins: [{
177
+ name: "hmr-auto-external",
178
+ setup(build$1) {
179
+ build$1.onResolve({ filter: /^[^./]/ }, async (args) => {
180
+ return {
181
+ path: args.path,
182
+ external: true
183
+ };
184
+ });
185
+ }
186
+ }, {
187
+ name: "resolve-server-functions",
188
+ setup(build$1) {
189
+ build$1.onResolve({ filter: /^\.\.?\/.*functions/ }, async (args) => {
190
+ const resolvedPath = path.resolve(path.dirname(args.importer), args.path);
191
+ const possibleExtensions = [
192
+ ".ts",
193
+ ".js",
194
+ ".tsx",
195
+ ".jsx",
196
+ "/index.ts",
197
+ "/index.js"
198
+ ];
199
+ for (const ext$1 of possibleExtensions) {
200
+ const fullPath = resolvedPath + ext$1;
201
+ if (fs.existsSync(fullPath)) return { path: fullPath };
202
+ }
203
+ return null;
204
+ });
205
+ }
206
+ }],
207
+ banner: { js: `// Rari Server Component Bundle
208
+ // Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
209
+ // Original file: ${path.relative(this.projectRoot, inputPath)}
210
+ ` }
211
+ });
212
+ if (result.outputFiles && result.outputFiles.length > 0) {
213
+ const outputFile = result.outputFiles[0];
214
+ const finalTransformedCode = this.createSelfRegisteringModule(outputFile.text, componentId);
215
+ return finalTransformedCode;
216
+ }
217
+ if (result.errors.length > 0) {
218
+ console.error("ESBuild errors:", result.errors);
219
+ throw new Error(`ESBuild compilation failed with ${result.errors.length} errors`);
220
+ }
221
+ throw new Error("No output generated from ESBuild");
222
+ } catch (error) {
223
+ console.error(`ESBuild failed for ${inputPath}:`, error);
224
+ throw error;
225
+ }
226
+ }
227
+ async buildServerComponents() {
228
+ const serverOutDir = path.join(this.options.outDir, this.options.serverDir);
229
+ await fs.promises.mkdir(serverOutDir, { recursive: true });
230
+ const manifest = {
231
+ components: {},
232
+ version: "1.0.0",
233
+ buildTime: (/* @__PURE__ */ new Date()).toISOString()
234
+ };
235
+ for (const [filePath, component] of this.serverComponents) {
236
+ const relativePath = path.relative(this.projectRoot, filePath);
237
+ const componentId = this.getComponentId(relativePath);
238
+ const bundlePath = path.join(this.options.serverDir, `${componentId}.js`);
239
+ const fullBundlePath = path.join(this.options.outDir, bundlePath);
240
+ const bundleDir = path.dirname(fullBundlePath);
241
+ await fs.promises.mkdir(bundleDir, { recursive: true });
242
+ await this.buildSingleComponent(filePath, fullBundlePath, component);
243
+ manifest.components[componentId] = {
244
+ id: componentId,
245
+ filePath,
246
+ relativePath,
247
+ bundlePath,
248
+ dependencies: component.dependencies,
249
+ hasNodeImports: component.hasNodeImports
250
+ };
251
+ }
252
+ const manifestPath = path.join(this.options.outDir, this.options.manifestPath);
253
+ await fs.promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
254
+ return manifest;
255
+ }
256
+ async buildSingleComponent(inputPath, outputPath, _component) {
257
+ const componentId = this.getComponentId(path.relative(this.projectRoot, inputPath));
258
+ const originalCode = await fs.promises.readFile(inputPath, "utf-8");
259
+ const clientTransformedCode = this.transformClientImports(originalCode, inputPath);
260
+ const transformedCode = this.transformNodeImports(clientTransformedCode);
261
+ const ext = path.extname(inputPath);
262
+ let loader;
263
+ if (ext === ".tsx") loader = "tsx";
264
+ else if (ext === ".ts") loader = "ts";
265
+ else if (ext === ".jsx") loader = "jsx";
266
+ else loader = "js";
267
+ try {
268
+ const result = await build({
269
+ stdin: {
270
+ contents: transformedCode,
271
+ resolveDir: path.dirname(inputPath),
272
+ sourcefile: inputPath,
273
+ loader
274
+ },
275
+ bundle: true,
276
+ platform: "neutral",
277
+ target: "es2022",
278
+ format: "esm",
279
+ outfile: outputPath,
280
+ external: [],
281
+ mainFields: ["module", "main"],
282
+ conditions: [
283
+ "import",
284
+ "module",
285
+ "default"
286
+ ],
287
+ define: {
288
+ "global": "globalThis",
289
+ "process.env.NODE_ENV": "\"production\""
290
+ },
291
+ loader: {
292
+ ".ts": "ts",
293
+ ".tsx": "tsx",
294
+ ".js": "js",
295
+ ".jsx": "jsx"
296
+ },
297
+ resolveExtensions: [
298
+ ".ts",
299
+ ".tsx",
300
+ ".js",
301
+ ".jsx"
302
+ ],
303
+ minify: false,
304
+ minifyIdentifiers: false,
305
+ sourcemap: false,
306
+ metafile: false,
307
+ write: false,
308
+ plugins: [{
309
+ name: "auto-external",
310
+ setup(build$1) {
311
+ build$1.onResolve({ filter: /^[^./]/ }, async (args) => {
312
+ return {
313
+ path: args.path,
314
+ external: true
315
+ };
316
+ });
317
+ }
318
+ }, {
319
+ name: "resolve-server-functions",
320
+ setup(build$1) {
321
+ build$1.onResolve({ filter: /^\.\.?\/.*functions/ }, async (args) => {
322
+ const resolvedPath = path.resolve(path.dirname(args.importer), args.path);
323
+ const possibleExtensions = [
324
+ ".ts",
325
+ ".js",
326
+ ".tsx",
327
+ ".jsx",
328
+ "/index.ts",
329
+ "/index.js"
330
+ ];
331
+ for (const ext$1 of possibleExtensions) {
332
+ const fullPath = resolvedPath + ext$1;
333
+ if (fs.existsSync(fullPath)) return { path: fullPath };
334
+ }
335
+ return null;
336
+ });
337
+ }
338
+ }],
339
+ banner: { js: `// Rari Server Component Bundle
340
+ // Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
341
+ // Original file: ${path.relative(this.projectRoot, inputPath)}
342
+ ` }
343
+ });
344
+ if (result.outputFiles && result.outputFiles.length > 0) {
345
+ const outputFile = result.outputFiles[0];
346
+ const finalTransformedCode = this.createSelfRegisteringModule(outputFile.text, componentId);
347
+ await fs.promises.writeFile(outputPath, finalTransformedCode, "utf-8");
348
+ }
349
+ if (result.errors.length > 0) {
350
+ console.error("ESBuild errors:", result.errors);
351
+ throw new Error(`ESBuild compilation failed with ${result.errors.length} errors`);
352
+ }
353
+ if (result.warnings.length > 0) console.warn("ESBuild warnings:", result.warnings);
354
+ } catch (error) {
355
+ console.error(`ESBuild failed for ${inputPath}:`, error);
356
+ throw error;
357
+ }
358
+ }
359
+ createSelfRegisteringModule(code, componentId) {
360
+ if (code.includes("Self-registering Production Component")) return code;
361
+ let transformedCode = code;
362
+ let defaultExportName = null;
363
+ const namedExports = [];
364
+ transformedCode = transformedCode.replace(/^export\s+default\s+function\s+(\w+)/gm, (match, name) => {
365
+ defaultExportName = name;
366
+ return `function ${name}`;
367
+ });
368
+ transformedCode = transformedCode.replace(/^export\s+default\s+async\s+function\s+(\w+)/gm, (match, name) => {
369
+ defaultExportName = name;
370
+ return `async function ${name}`;
371
+ });
372
+ transformedCode = transformedCode.replace(/^export\s+default\s+(\w+);?\s*$/gm, (match, name) => {
373
+ defaultExportName = name;
374
+ return `// Default export: ${name}`;
375
+ });
376
+ transformedCode = transformedCode.replace(/^export\s*\{\s*(\w+)\s+as\s+default\s*\};?\s*$/gm, (match, name) => {
377
+ defaultExportName = name;
378
+ return `// Default export: ${name}`;
379
+ });
380
+ transformedCode = transformedCode.replace(/^export\s*\{([^}]+)\};?\s*$/gm, (match, exports) => {
381
+ const exportList = exports.split(",").map((exp) => exp.trim());
382
+ exportList.forEach((exp) => {
383
+ if (exp.includes("as default")) {
384
+ const actualName = exp.replace("as default", "").trim();
385
+ defaultExportName = actualName;
386
+ } else if (exp === "default") {
387
+ const possibleDefault = `${componentId}_default`;
388
+ if (transformedCode.includes(`var ${possibleDefault}`)) defaultExportName = possibleDefault;
389
+ } else namedExports.push(exp);
390
+ });
391
+ return `// Exports: ${exports}`;
392
+ });
393
+ transformedCode = transformedCode.replace(/^export\s+(?:async\s+)?function\s+(\w+)/gm, (match, name) => {
394
+ namedExports.push(name);
395
+ return match.replace("export ", "");
396
+ });
397
+ transformedCode = transformedCode.replace(/^export\s+(const|let|var)\s+(\w+)/gm, (match, keyword, name) => {
398
+ namedExports.push(name);
399
+ return `${keyword} ${name}`;
400
+ });
401
+ if (!defaultExportName) {
402
+ const possibleDefault = `${componentId}_default`;
403
+ if (transformedCode.includes(`var ${possibleDefault}`)) defaultExportName = possibleDefault;
404
+ }
405
+ const mainExport = defaultExportName || componentId;
406
+ const selfRegisteringCode = `// Self-registering Production Component: ${componentId}
407
+ "use module";
408
+
409
+ // Original component code with exports removed for self-registration
410
+ ${transformedCode}
411
+
412
+ // Self-registration logic
413
+ (function() {
414
+ try {
415
+ const moduleKey = "${componentId}";
416
+ const registrationKey = "Component_${Math.random().toString(36).substr(2, 8)}";
417
+ let mainExport = null;
418
+ let exportedFunctions = {};
419
+
420
+ globalThis.__rsc_functions = globalThis.__rsc_functions || {};
421
+
422
+ // Register named exports
423
+ ${namedExports.map((name) => `
424
+ if (typeof ${name} !== 'undefined') {
425
+ globalThis.${name} = ${name};
426
+ globalThis.__rsc_functions['${name}'] = ${name};
427
+ exportedFunctions['${name}'] = ${name};
428
+ }`).join("")}
429
+
430
+ // Set main export
431
+ if (typeof ${mainExport} !== 'undefined') {
432
+ mainExport = ${mainExport};
433
+ } else {
434
+ const potentialExports = {};
435
+ ${namedExports.map((name) => `if (typeof ${name} !== 'undefined') potentialExports.${name} = ${name};`).join("\n ")}
436
+
437
+ if (Object.keys(potentialExports).length > 0) {
438
+ if (Object.keys(potentialExports).length === 1) {
439
+ mainExport = potentialExports[Object.keys(potentialExports)[0]];
440
+ } else {
441
+ mainExport = potentialExports;
442
+ }
443
+ }
444
+ }
445
+
446
+ if (mainExport !== null) {
447
+ if (!globalThis[moduleKey]) {
448
+ globalThis[moduleKey] = mainExport;
449
+ }
450
+
451
+ if (!globalThis[registrationKey]) {
452
+ globalThis[registrationKey] = mainExport;
453
+ }
454
+
455
+ if (typeof globalThis.RscModuleManager !== 'undefined' && globalThis.RscModuleManager.register) {
456
+ globalThis.RscModuleManager.register(moduleKey, mainExport, exportedFunctions);
457
+ }
458
+ }
459
+ } catch (error) {
460
+ console.error('Error in self-registration for ${componentId}:', error);
461
+ }
462
+ })();`;
463
+ return selfRegisteringCode;
464
+ }
465
+ transformClientImports(code, inputPath) {
466
+ let transformedCode = code;
467
+ const importRegex = /import\s+(\w+)(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]([./][^'"]+)['"];?\s*$/gm;
468
+ let match;
469
+ const replacements = [];
470
+ let hasClientComponents = false;
471
+ while (true) {
472
+ match = importRegex.exec(code);
473
+ if (match === null) break;
474
+ const [fullMatch, defaultImport, importPath] = match;
475
+ const resolvedPath = this.resolveImportPath(importPath, inputPath);
476
+ if (this.isClientComponent(resolvedPath)) {
477
+ hasClientComponents = true;
478
+ const componentName = defaultImport || "default";
479
+ const replacement = `const ${componentName} = registerClientReference(
480
+ null,
481
+ ${JSON.stringify(path.relative(this.projectRoot, resolvedPath))},
482
+ "default"
483
+ );`;
484
+ replacements.push({
485
+ original: fullMatch,
486
+ replacement
487
+ });
488
+ }
489
+ }
490
+ if (hasClientComponents) {
491
+ const functionDefinition = `
492
+ // registerClientReference function for client components
493
+ function registerClientReference(clientReference, id, exportName) {
494
+ const key = id + '#' + exportName;
495
+
496
+ const clientProxy = {};
497
+
498
+ Object.defineProperty(clientProxy, '$$typeof', {
499
+ value: Symbol.for('react.client.reference'),
500
+ enumerable: false
501
+ });
502
+
503
+ Object.defineProperty(clientProxy, '$$id', {
504
+ value: key,
505
+ enumerable: false
506
+ });
507
+
508
+ Object.defineProperty(clientProxy, '$$async', {
509
+ value: false,
510
+ enumerable: false
511
+ });
512
+
513
+ try {
514
+ if (typeof globalThis.__rari_bridge !== 'undefined' &&
515
+ typeof globalThis.__rari_bridge.registerClientReference === 'function') {
516
+ globalThis.__rari_bridge.registerClientReference(key, id, exportName);
517
+ }
518
+ } catch (error) {
519
+ console.error('Failed to register client reference with Rust bridge:', error);
520
+ }
521
+
522
+ return clientProxy;
523
+ }
524
+
525
+ `;
526
+ transformedCode = functionDefinition + transformedCode;
527
+ }
528
+ for (const { original, replacement } of replacements) transformedCode = transformedCode.replace(original, replacement);
529
+ return transformedCode;
530
+ }
531
+ resolveImportPath(importPath, importerPath) {
532
+ const resolvedPath = path.resolve(path.dirname(importerPath), importPath);
533
+ const extensions = [
534
+ ".tsx",
535
+ ".jsx",
536
+ ".ts",
537
+ ".js"
538
+ ];
539
+ for (const ext of extensions) {
540
+ const pathWithExt = `${resolvedPath}${ext}`;
541
+ if (fs.existsSync(pathWithExt)) return pathWithExt;
542
+ }
543
+ if (fs.existsSync(resolvedPath)) for (const ext of extensions) {
544
+ const indexPath = path.join(resolvedPath, `index${ext}`);
545
+ if (fs.existsSync(indexPath)) return indexPath;
546
+ }
547
+ return `${resolvedPath}.tsx`;
548
+ }
549
+ transformNodeImports(code) {
550
+ let transformedCode = code;
551
+ transformedCode = transformedCode.replace(/import\s+(\w+)\s+from\s+['"]node:process['"];?\s*$/gm, (match, importName) => {
552
+ return `const ${importName} = globalThis.process;`;
553
+ });
554
+ transformedCode = transformedCode.replace(/import\s+\{([^}]+)\}\s+from\s+['"]node:fs['"];?\s*$/gm, (match, imports) => {
555
+ const importList = imports.split(",").map((imp) => imp.trim());
556
+ return importList.map((imp) => {
557
+ const cleanImp = imp.replace(/\s+as\s+\w+/, "");
558
+ if (cleanImp === "existsSync") return `const ${cleanImp} = (path) => { try { if (globalThis.Deno?.statSync) { globalThis.Deno.statSync(path); return true; } return false; } catch (error) { return false; } };`;
559
+ if (cleanImp === "readFileSync") return `const ${cleanImp} = (path, encoding = 'utf8') => globalThis.Deno.readTextFileSync(path);`;
560
+ return `const ${cleanImp} = globalThis.Deno?.${cleanImp} || (() => { throw new Error('${cleanImp} not available'); });`;
561
+ }).join("\n");
562
+ });
563
+ transformedCode = transformedCode.replace(/import\s+\{([^}]+)\}\s+from\s+['"]node:path['"];?\s*$/gm, (match, imports) => {
564
+ const importList = imports.split(",").map((imp) => imp.trim());
565
+ return importList.map((imp) => {
566
+ const cleanImp = imp.replace(/\s+as\s+\w+/, "");
567
+ if (cleanImp === "join") return `const ${cleanImp} = (...paths) => paths.filter(Boolean).join('/').replace(/\\/+/g, '/');`;
568
+ return `const ${cleanImp} = globalThis.path?.${cleanImp} || (() => { throw new Error('${cleanImp} not available'); });`;
569
+ }).join("\n");
570
+ });
571
+ transformedCode = transformedCode.replace(/import\s+\{([^}]+)\}\s+from\s+['"]node:process['"];?\s*$/gm, (match, imports) => {
572
+ const importList = imports.split(",").map((imp) => imp.trim());
573
+ return importList.map((imp) => {
574
+ const cleanImp = imp.replace(/\s+as\s+\w+/, "");
575
+ if (cleanImp === "cwd") return `const ${cleanImp} = () => globalThis.Deno?.cwd?.() || '.';`;
576
+ return `const ${cleanImp} = globalThis.process?.${cleanImp} || (() => { throw new Error('${cleanImp} not available'); });`;
577
+ }).join("\n");
578
+ });
579
+ return transformedCode;
580
+ }
581
+ getComponentId(relativePath) {
582
+ return relativePath.replace(/\\/g, "/").replace(/\.(tsx?|jsx?)$/, "").replace(/[^\w/-]/g, "_").replace(/^src\//, "").replace(/^components\//, "");
583
+ }
584
+ };
585
+ function scanDirectory(dir, builder) {
586
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
587
+ for (const entry of entries) {
588
+ const fullPath = path.join(dir, entry.name);
589
+ if (entry.isDirectory()) scanDirectory(fullPath, builder);
590
+ else if (entry.isFile() && /\.(?:tsx?|jsx?)$/.test(entry.name)) try {
591
+ if (builder.isServerComponent(fullPath)) builder.addServerComponent(fullPath);
592
+ } catch (error) {
593
+ console.warn(`[server-build] Error checking ${fullPath}:`, error instanceof Error ? error.message : error);
594
+ }
595
+ }
596
+ }
597
+ function createServerBuildPlugin(options = {}) {
598
+ let builder = null;
599
+ let projectRoot;
600
+ return {
601
+ name: "rari-server-build",
602
+ configResolved(config) {
603
+ projectRoot = config.root;
604
+ builder = new ServerComponentBuilder(projectRoot, options);
605
+ },
606
+ buildStart() {
607
+ if (!builder) return;
608
+ const srcDir = path.join(projectRoot, "src");
609
+ if (fs.existsSync(srcDir)) scanDirectory(srcDir, builder);
610
+ },
611
+ async closeBundle() {
612
+ if (builder) await builder.buildServerComponents();
613
+ }
614
+ };
615
+ }
616
+
617
+ //#endregion
618
+ export { ServerComponentBuilder, createServerBuildPlugin, scanDirectory };
@@ -0,0 +1,3 @@
1
+ import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-BEWMJWMx.js";
2
+ import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-MY0-nRif.js";
3
+ export { ErrorBoundaryProps, FileRouteGenerator, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, RouteComponent as Route, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, Route as RouteType, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };