raktajs 0.1.2 → 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.
package/dist/cli/rakta.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // @bun
3
3
 
4
4
  // src/cli/rakta.ts
5
- import { join as join17 } from "path";
5
+ import { join as join18 } from "path";
6
6
 
7
7
  // src/config/loadConfig.ts
8
8
  import { existsSync } from "fs";
@@ -474,18 +474,225 @@ function printInspectReport(report) {
474
474
  }
475
475
 
476
476
  // src/cli/build.ts
477
- import { isAbsolute, join as join5 } from "path";
477
+ import { isAbsolute, join as join6 } from "path";
478
+
479
+ // src/forge/build.ts
480
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
481
+ import { join as join5, resolve as resolve2 } from "path";
482
+
483
+ // src/forge/clientEntry.ts
484
+ import { existsSync as existsSync5, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
485
+ import { dirname, join as join4, relative as relative2 } from "path";
486
+ function toModuleSpecifier(fromFile, targetFile) {
487
+ const relativePath = relative2(dirname(fromFile), targetFile).replace(/\\/g, "/");
488
+ if (relativePath.startsWith(".")) {
489
+ return relativePath;
490
+ }
491
+ return `./${relativePath}`;
492
+ }
493
+ function toCssImportSpecifier(entryPath, projectRoot) {
494
+ const candidates = [
495
+ join4(projectRoot, "styles", "globals.css"),
496
+ join4(projectRoot, "styles", "globals.scss"),
497
+ join4(projectRoot, "styles", "globals.sass")
498
+ ];
499
+ const stylePath = candidates.find((candidate) => existsSync5(candidate));
500
+ if (!stylePath) {
501
+ return null;
502
+ }
503
+ return toModuleSpecifier(entryPath, stylePath);
504
+ }
505
+ function getPageRoutes(manifest) {
506
+ return manifest.routes.filter((route) => route.kind === "page");
507
+ }
508
+ function buildRouteImports(entryPath, appDir, pageRoutes) {
509
+ const routeEntries = pageRoutes.map((route) => {
510
+ const pagePath = join4(appDir, route.filePath);
511
+ return ` ${JSON.stringify(route.urlPattern)}: () => import("${toModuleSpecifier(entryPath, pagePath)}"),`;
512
+ }).join(`
513
+ `);
514
+ return `const routeModules = {
515
+ ${routeEntries}
516
+ } as const;`;
517
+ }
518
+ function buildRouteTable(pageRoutes) {
519
+ const routeEntries = pageRoutes.map((route) => ` ${JSON.stringify(route.urlPattern)}: routeModules[${JSON.stringify(route.urlPattern)}],`).join(`
520
+ `);
521
+ return `const routes = {
522
+ ${routeEntries}
523
+ } as const;`;
524
+ }
525
+ function findExistingModule(basePathWithoutExtension) {
526
+ const candidates = [".tsx", ".ts", ".jsx", ".js"].map((extension) => `${basePathWithoutExtension}${extension}`);
527
+ return candidates.find((candidate) => existsSync5(candidate));
528
+ }
529
+ function buildStarterGlobalLoaders(entryPath, appDir) {
530
+ const mascotPath = findExistingModule(join4(appDir, "components", "raktaShrimpMascot"));
531
+ const gamePath = findExistingModule(join4(appDir, "components", "shrimpRunGame"));
532
+ const loaders = [];
533
+ if (mascotPath !== undefined) {
534
+ loaders.push(` const mascotModule = await import("${toModuleSpecifier(entryPath, mascotPath)}");
535
+ (globalThis as typeof globalThis & Record<string, unknown>).RaktaShrimpMascot = mascotModule.default;`);
536
+ }
537
+ if (gamePath !== undefined) {
538
+ loaders.push(` const gameModule = await import("${toModuleSpecifier(entryPath, gamePath)}");
539
+ (globalThis as typeof globalThis & Record<string, unknown>).ShrimpRunGame = gameModule.default;`);
540
+ }
541
+ if (loaders.length === 0) {
542
+ return `async function loadRaktaGlobals(): Promise<void> {
543
+ return;
544
+ }`;
545
+ }
546
+ return `async function loadRaktaGlobals(): Promise<void> {
547
+ ${loaders.join(`
548
+
549
+ `)}
550
+ }`;
551
+ }
552
+ function buildClientEntrySource(options, entryPath) {
553
+ const pageRoutes = getPageRoutes(options.manifest);
554
+ const routeModules = buildRouteImports(entryPath, options.appDir, pageRoutes);
555
+ const routeTable = buildRouteTable(pageRoutes);
556
+ const cssImportSpecifier = toCssImportSpecifier(entryPath, options.projectRoot);
557
+ const cssImport = cssImportSpecifier !== null ? `import "${cssImportSpecifier}";
558
+ ` : "";
559
+ const starterGlobalLoaders = buildStarterGlobalLoaders(entryPath, options.appDir);
560
+ return `import React, { useEffect, useState } from "react";
561
+ import { createRoot } from "react-dom/client";
562
+ import * as ReactHooks from "react";
563
+ ${cssImport}
564
+ (globalThis as typeof globalThis & Record<string, unknown>).useCallback = ReactHooks.useCallback;
565
+ (globalThis as typeof globalThis & Record<string, unknown>).useEffect = ReactHooks.useEffect;
566
+ (globalThis as typeof globalThis & Record<string, unknown>).useRef = ReactHooks.useRef;
567
+ (globalThis as typeof globalThis & Record<string, unknown>).useState = ReactHooks.useState;
568
+
569
+ ${starterGlobalLoaders}
570
+
571
+ await loadRaktaGlobals();
572
+
573
+ ${routeModules}
574
+
575
+ ${routeTable}
576
+
577
+ type RoutePath = keyof typeof routes;
578
+ type PageModule = { default: React.ComponentType };
579
+
580
+ function normalizePathname(pathname: string): string {
581
+ if (pathname.length > 1 && pathname.endsWith("/")) {
582
+ return pathname.slice(0, -1);
583
+ }
584
+
585
+ return pathname;
586
+ }
587
+
588
+ function resolveRouteLoader(pathname: string): () => Promise<PageModule> {
589
+ const normalizedPathname = normalizePathname(pathname) as RoutePath;
590
+
591
+ return routes[normalizedPathname] ?? routes["/"];
592
+ }
593
+
594
+ function navigate(to: string): void {
595
+ window.history.pushState({ source: "rakta-click", to }, "", to);
596
+ window.dispatchEvent(new PopStateEvent("popstate", { state: { to } }));
597
+ }
598
+
599
+ function App(): React.ReactElement {
600
+ const [pathname, setPathname] = useState(() => window.location.pathname);
601
+ const [Page, setPage] = useState<React.ComponentType | null>(null);
602
+
603
+ useEffect(() => {
604
+ function handlePopState(): void {
605
+ setPathname(window.location.pathname);
606
+ }
607
+
608
+ function handleClick(event: MouseEvent): void {
609
+ const target = event.target;
610
+
611
+ if (!(target instanceof Element)) {
612
+ return;
613
+ }
614
+
615
+ const clickElement = target.closest("click");
616
+
617
+ if (!clickElement) {
618
+ return;
619
+ }
620
+
621
+ const to = clickElement.getAttribute("to");
622
+
623
+ if (!to || to.startsWith("http://") || to.startsWith("https://")) {
624
+ return;
625
+ }
626
+
627
+ event.preventDefault();
628
+ navigate(to);
629
+ setPathname(window.location.pathname);
630
+ }
631
+
632
+ window.addEventListener("popstate", handlePopState);
633
+ document.addEventListener("click", handleClick);
634
+
635
+ return () => {
636
+ window.removeEventListener("popstate", handlePopState);
637
+ document.removeEventListener("click", handleClick);
638
+ };
639
+ }, []);
640
+
641
+ useEffect(() => {
642
+ let isCurrent = true;
643
+
644
+ resolveRouteLoader(pathname)().then((pageModule) => {
645
+ if (isCurrent) {
646
+ setPage(() => pageModule.default);
647
+ }
648
+ });
649
+
650
+ return () => {
651
+ isCurrent = false;
652
+ };
653
+ }, [pathname]);
654
+
655
+ if (!Page) {
656
+ return React.createElement("main", {
657
+ style: {
658
+ minHeight: "100vh",
659
+ display: "grid",
660
+ placeItems: "center",
661
+ background: "#050505",
662
+ color: "#f8fafc",
663
+ fontFamily: "ui-sans-serif, system-ui, sans-serif",
664
+ },
665
+ }, "Loading Rakta.js...");
666
+ }
667
+
668
+ return React.createElement(Page);
669
+ }
670
+
671
+ const rootElement = document.getElementById("rakta-root");
672
+
673
+ if (!rootElement) {
674
+ throw new Error("Rakta.js root element #rakta-root was not found.");
675
+ }
676
+
677
+ createRoot(rootElement).render(React.createElement(App));
678
+ `;
679
+ }
680
+ function writeClientEntry(options) {
681
+ mkdirSync(options.workDir, { recursive: true });
682
+ const entryPath = join4(options.workDir, "client-entry.tsx");
683
+ const entrySource = buildClientEntrySource(options, entryPath);
684
+ writeFileSync2(entryPath, entrySource, "utf-8");
685
+ return entryPath;
686
+ }
478
687
 
479
688
  // src/forge/build.ts
480
- import { mkdirSync } from "fs";
481
- import { join as join4, resolve as resolve2 } from "path";
482
689
  async function buildProject(options) {
483
690
  const startMs = Date.now();
484
691
  const artifacts = [];
485
692
  const errors = [];
486
- mkdirSync(resolve2(options.outDir), { recursive: true });
693
+ mkdirSync2(resolve2(options.outDir), { recursive: true });
487
694
  const manifest = generateManifest(options.appDir);
488
- const manifestPath = join4(options.outDir, "route-manifest.json");
695
+ const manifestPath = join5(options.outDir, "route-manifest.json");
489
696
  writeManifest(manifest, manifestPath);
490
697
  const manifestContent = JSON.stringify(manifest);
491
698
  artifacts.push({
@@ -493,15 +700,21 @@ async function buildProject(options) {
493
700
  sizeBytes: new TextEncoder().encode(manifestContent).byteLength,
494
701
  kind: "manifest"
495
702
  });
703
+ const entryPoint = existsSync6(options.entryPoint) ? options.entryPoint : writeClientEntry({
704
+ projectRoot: options.projectRoot,
705
+ appDir: options.appDir,
706
+ workDir: join5(options.projectRoot, ".rakta"),
707
+ manifest
708
+ });
496
709
  const buildResult = await Bun.build({
497
- entrypoints: [options.entryPoint],
710
+ entrypoints: [entryPoint],
498
711
  outdir: options.outDir,
499
712
  target: options.target,
500
713
  minify: options.minify,
501
714
  sourcemap: options.sourcemap ? "external" : "none",
502
715
  splitting: options.splitting,
503
716
  naming: {
504
- entry: "[name].[ext]",
717
+ entry: "app.[ext]",
505
718
  chunk: "chunks/[name]-[hash].[ext]",
506
719
  asset: "assets/[name]-[hash].[ext]"
507
720
  }
@@ -539,7 +752,7 @@ function resolveProjectPath(cwd, pathValue) {
539
752
  if (isAbsolute(pathValue)) {
540
753
  return pathValue;
541
754
  }
542
- return join5(cwd, pathValue);
755
+ return join6(cwd, pathValue);
543
756
  }
544
757
  async function buildCommand(cwd = process.cwd()) {
545
758
  const projectConfig = await loadConfig(cwd);
@@ -547,16 +760,17 @@ async function buildCommand(cwd = process.cwd()) {
547
760
  const publicDirectory = projectConfig.publicDir ?? "public";
548
761
  const outputDirectory = projectConfig.build.outDir ?? "dist";
549
762
  const entryFile = projectConfig.build.entryPoint ?? "entry.client.tsx";
550
- const entryPoint = resolveProjectPath(join5(cwd, appDirectory), entryFile);
763
+ const entryPoint = resolveProjectPath(join6(cwd, appDirectory), entryFile);
551
764
  const outDir = resolveProjectPath(cwd, outputDirectory);
552
765
  console.log(`
553
766
  Building Rakta.js application...
554
767
  `);
555
768
  const buildResult = await buildProject({
769
+ projectRoot: cwd,
556
770
  entryPoint,
557
771
  outDir,
558
- appDir: join5(cwd, appDirectory),
559
- publicDir: join5(cwd, publicDirectory),
772
+ appDir: join6(cwd, appDirectory),
773
+ publicDir: join6(cwd, publicDirectory),
560
774
  appName: projectConfig.appName,
561
775
  sourcemap: projectConfig.build.sourcemap ?? false,
562
776
  minify: projectConfig.build.minify ?? true,
@@ -578,11 +792,11 @@ async function buildCommand(cwd = process.cwd()) {
578
792
  }
579
793
 
580
794
  // src/cli/dev.ts
581
- import { join as join7 } from "path";
795
+ import { join as join8 } from "path";
582
796
 
583
797
  // src/forge/devServer.ts
584
- import { existsSync as existsSync5, readFileSync as readFileSync2, statSync as statSync3 } from "fs";
585
- import { join as join6 } from "path";
798
+ import { existsSync as existsSync7, readFileSync as readFileSync2, statSync as statSync3 } from "fs";
799
+ import { join as join7 } from "path";
586
800
 
587
801
  // src/render/renderer.ts
588
802
  function buildHtmlShell(options) {
@@ -700,18 +914,55 @@ function resolveDevPort(port) {
700
914
  return port > 0 ? port : DEFAULT_DEV_PORT;
701
915
  }
702
916
  function isReadableFile(filePath) {
703
- return existsSync5(filePath) && statSync3(filePath).isFile();
917
+ return existsSync7(filePath) && statSync3(filePath).isFile();
918
+ }
919
+ async function buildDevClientBundle(options, manifest) {
920
+ const workDir = join7(options.projectRoot, ".rakta");
921
+ const clientOutDir = join7(workDir, "dev");
922
+ const clientEntry = writeClientEntry({
923
+ projectRoot: options.projectRoot,
924
+ appDir: options.appDir,
925
+ workDir,
926
+ manifest
927
+ });
928
+ const buildResult = await Bun.build({
929
+ entrypoints: [clientEntry],
930
+ outdir: clientOutDir,
931
+ target: "browser",
932
+ sourcemap: "external",
933
+ naming: {
934
+ entry: "app.[ext]",
935
+ chunk: "chunks/[name]-[hash].[ext]",
936
+ asset: "assets/[name]-[hash].[ext]"
937
+ }
938
+ });
939
+ if (!buildResult.success) {
940
+ const buildErrors = buildResult.logs.map((buildLog) => buildLog.message).join(`
941
+ `);
942
+ throw new Error(`Failed to build Rakta.js client bundle.
943
+ ${buildErrors}`);
944
+ }
945
+ return clientOutDir;
704
946
  }
705
- function startDevServer(options) {
947
+ async function startDevServer(options) {
706
948
  const manifest = generateManifest(options.appDir);
707
949
  const resolvedPort = resolveDevPort(options.port);
950
+ const clientOutDir = await buildDevClientBundle(options, manifest);
708
951
  const server = Bun.serve({
709
952
  port: resolvedPort,
710
953
  hostname: options.host,
711
954
  async fetch(request) {
712
955
  const url = new URL(request.url);
713
956
  const { pathname } = url;
714
- const publicPath = join6(options.publicDir, pathname);
957
+ if (clientOutDir.length > 0) {
958
+ const clientBundlePath = join7(clientOutDir, pathname);
959
+ if (isReadableFile(clientBundlePath)) {
960
+ return new Response(readFileSync2(clientBundlePath), {
961
+ headers: { "Content-Type": resolveMime(clientBundlePath) }
962
+ });
963
+ }
964
+ }
965
+ const publicPath = join7(options.publicDir, pathname);
715
966
  if (isReadableFile(publicPath)) {
716
967
  return new Response(readFileSync2(publicPath), {
717
968
  headers: { "Content-Type": resolveMime(pathname) }
@@ -719,7 +970,7 @@ function startDevServer(options) {
719
970
  }
720
971
  const apiMatch = matchRoute(pathname, manifest.routes.filter((route) => route.kind === "api"));
721
972
  if (apiMatch) {
722
- const modulePath = join6(options.appDir, apiMatch.entry.filePath);
973
+ const modulePath = join7(options.appDir, apiMatch.entry.filePath);
723
974
  const routeModule = await import(modulePath);
724
975
  const method = request.method.toUpperCase();
725
976
  const handler = routeModule[method];
@@ -747,7 +998,7 @@ function startDevServer(options) {
747
998
  }, {
748
999
  appName: options.appName,
749
1000
  scriptPath: "/app.js",
750
- cssPath: "/globals.css",
1001
+ cssPath: "/app.css",
751
1002
  lang: "en"
752
1003
  });
753
1004
  if (result.kind === "failure") {
@@ -774,19 +1025,22 @@ async function devCommand(cwd = process.cwd()) {
774
1025
  console.log(`
775
1026
  Starting Rakta.js dev server...
776
1027
  `);
777
- startDevServer({
1028
+ const server = await startDevServer({
1029
+ projectRoot: cwd,
778
1030
  port: config.port,
779
1031
  host: config.server.hostname ?? "0.0.0.0",
780
- appDir: join7(cwd, config.appDir),
781
- publicDir: join7(cwd, config.publicDir),
1032
+ appDir: join8(cwd, config.appDir),
1033
+ publicDir: join8(cwd, config.publicDir),
782
1034
  appName: config.appName,
783
1035
  renderConfig: config.render
784
1036
  });
1037
+ console.log(` Ready at ${server.url}
1038
+ `);
785
1039
  }
786
1040
 
787
1041
  // src/cli/doctor.ts
788
- import { existsSync as existsSync6 } from "fs";
789
- import { join as join8 } from "path";
1042
+ import { existsSync as existsSync8 } from "fs";
1043
+ import { join as join9 } from "path";
790
1044
  async function doctorCommand(cwd = process.cwd()) {
791
1045
  const config = await loadConfig(cwd);
792
1046
  const checks = [
@@ -797,31 +1051,31 @@ async function doctorCommand(cwd = process.cwd()) {
797
1051
  },
798
1052
  {
799
1053
  label: "rakta.config.ts",
800
- passed: existsSync6(join8(cwd, "rakta.config.ts")) || existsSync6(join8(cwd, "rakta.config.js"))
1054
+ passed: existsSync8(join9(cwd, "rakta.config.ts")) || existsSync8(join9(cwd, "rakta.config.js"))
801
1055
  },
802
1056
  {
803
1057
  label: `app/ directory (${config.appDir})`,
804
- passed: existsSync6(join8(cwd, config.appDir))
1058
+ passed: existsSync8(join9(cwd, config.appDir))
805
1059
  },
806
1060
  {
807
1061
  label: "app/page.tsx (root page)",
808
- passed: existsSync6(join8(cwd, config.appDir, "page.tsx"))
1062
+ passed: existsSync8(join9(cwd, config.appDir, "page.tsx"))
809
1063
  },
810
1064
  {
811
1065
  label: "app/layout.tsx (root layout)",
812
- passed: existsSync6(join8(cwd, config.appDir, "layout.tsx"))
1066
+ passed: existsSync8(join9(cwd, config.appDir, "layout.tsx"))
813
1067
  },
814
1068
  {
815
1069
  label: `public/ directory (${config.publicDir})`,
816
- passed: existsSync6(join8(cwd, config.publicDir))
1070
+ passed: existsSync8(join9(cwd, config.publicDir))
817
1071
  },
818
1072
  {
819
1073
  label: "package.json",
820
- passed: existsSync6(join8(cwd, "package.json"))
1074
+ passed: existsSync8(join9(cwd, "package.json"))
821
1075
  },
822
1076
  {
823
1077
  label: "tsconfig.json",
824
- passed: existsSync6(join8(cwd, "tsconfig.json"))
1078
+ passed: existsSync8(join9(cwd, "tsconfig.json"))
825
1079
  }
826
1080
  ];
827
1081
  const sep = "\u2500".repeat(52);
@@ -848,12 +1102,12 @@ async function doctorCommand(cwd = process.cwd()) {
848
1102
  }
849
1103
 
850
1104
  // src/auto-import/generator.ts
851
- import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
852
- import { join as join10 } from "path";
1105
+ import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
1106
+ import { join as join11 } from "path";
853
1107
 
854
1108
  // src/auto-import/scanner.ts
855
- import { existsSync as existsSync7, readdirSync as readdirSync3 } from "fs";
856
- import { basename, extname, join as join9, relative as relative2 } from "path";
1109
+ import { existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
1110
+ import { basename, extname, join as join10, relative as relative3 } from "path";
857
1111
  var DEFAULT_EXTENSIONS = [
858
1112
  ".ts",
859
1113
  ".tsx",
@@ -884,12 +1138,12 @@ function toPascalCase(text) {
884
1138
  return text.replace(/[-_.]/g, " ").replace(/\s+(.)/g, (_match, char) => char.toUpperCase()).replace(/^(.)/, (_match, char) => char.toUpperCase());
885
1139
  }
886
1140
  function deriveExportName(filePath, dirPath) {
887
- const relativePath = relative2(dirPath, filePath).replace(/\\/g, "/");
1141
+ const relativePath = relative3(dirPath, filePath).replace(/\\/g, "/");
888
1142
  const withoutExtension = relativePath.replace(/\.(ts|tsx|js|jsx)$/, "").replace(/\/index$/, "");
889
1143
  return toPascalCase(withoutExtension.replace(/\//g, "_"));
890
1144
  }
891
1145
  function walkDirectory(dirPath, extensions) {
892
- if (!existsSync7(dirPath)) {
1146
+ if (!existsSync9(dirPath)) {
893
1147
  return [];
894
1148
  }
895
1149
  const collected = [];
@@ -901,7 +1155,7 @@ function walkDirectory(dirPath, extensions) {
901
1155
  if (entry.name.startsWith(".") || entry.name === "node_modules") {
902
1156
  continue;
903
1157
  }
904
- const fullPath = join9(currentPath, entry.name);
1158
+ const fullPath = join10(currentPath, entry.name);
905
1159
  if (entry.isDirectory()) {
906
1160
  walk(fullPath);
907
1161
  continue;
@@ -917,16 +1171,16 @@ function walkDirectory(dirPath, extensions) {
917
1171
  function scanForExports(options) {
918
1172
  const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
919
1173
  const discovered = [];
920
- const outputAbs = join9(options.frontendRoot, options.outputDirectory);
1174
+ const outputAbs = join10(options.frontendRoot, options.outputDirectory);
921
1175
  for (const directory of options.directories) {
922
- const directoryAbs = join9(options.frontendRoot, directory);
1176
+ const directoryAbs = join10(options.frontendRoot, directory);
923
1177
  const files = walkDirectory(directoryAbs, extensions);
924
1178
  for (const filePath of files) {
925
- const relativeFromOutput = relative2(outputAbs, filePath).replace(/\\/g, "/").replace(/\.(ts|tsx)$/, "");
1179
+ const relativeFromOutput = relative3(outputAbs, filePath).replace(/\\/g, "/").replace(/\.(ts|tsx)$/, "");
926
1180
  const importPath = relativeFromOutput.startsWith(".") ? relativeFromOutput : `./${relativeFromOutput}`;
927
1181
  discovered.push({
928
1182
  name: deriveExportName(filePath, directoryAbs),
929
- filePath: relative2(options.frontendRoot, filePath).replace(/\\/g, "/"),
1183
+ filePath: relative3(options.frontendRoot, filePath).replace(/\\/g, "/"),
930
1184
  importPath,
931
1185
  kind: detectKind(filePath)
932
1186
  });
@@ -959,17 +1213,17 @@ function generateAutoImports(options) {
959
1213
  extensions: options.extensions
960
1214
  } : {}
961
1215
  });
962
- const outputDir = join10(options.frontendRoot, options.outputDirectory);
963
- mkdirSync2(outputDir, {
1216
+ const outputDir = join11(options.frontendRoot, options.outputDirectory);
1217
+ mkdirSync3(outputDir, {
964
1218
  recursive: true
965
1219
  });
966
1220
  const tsContent = `${GENERATED_HEADER}
967
1221
  ${buildImportLines(exports)}
968
1222
  `;
969
- writeFileSync2(join10(outputDir, "auto-imports.ts"), tsContent, "utf-8");
1223
+ writeFileSync3(join11(outputDir, "auto-imports.ts"), tsContent, "utf-8");
970
1224
  if (options.generateDts) {
971
1225
  const dtsContent = tsContent.replace("// This file is auto-generated by: bun rakta imports:generate", "// Type declarations \u2014 auto-generated by: bun rakta imports:generate");
972
- writeFileSync2(join10(outputDir, "auto-imports.d.ts"), dtsContent, "utf-8");
1226
+ writeFileSync3(join11(outputDir, "auto-imports.d.ts"), dtsContent, "utf-8");
973
1227
  }
974
1228
  return {
975
1229
  generatedAt: new Date().toISOString(),
@@ -1011,18 +1265,18 @@ async function importsGenerateCommand(cwd = process.cwd()) {
1011
1265
  }
1012
1266
 
1013
1267
  // src/cli/make.ts
1014
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
1015
- import { dirname, join as join11 } from "path";
1268
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
1269
+ import { dirname as dirname2, join as join12 } from "path";
1016
1270
  function toPascalCase2(name) {
1017
1271
  return name.split(/[-_/]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
1018
1272
  }
1019
1273
  function writeIfNew(filePath, content) {
1020
- if (existsSync8(filePath)) {
1274
+ if (existsSync10(filePath)) {
1021
1275
  console.warn(` Already exists: ${filePath}`);
1022
1276
  return;
1023
1277
  }
1024
- mkdirSync3(dirname(filePath), { recursive: true });
1025
- writeFileSync3(filePath, content, "utf-8");
1278
+ mkdirSync4(dirname2(filePath), { recursive: true });
1279
+ writeFileSync4(filePath, content, "utf-8");
1026
1280
  console.log(` Created: ${filePath}`);
1027
1281
  }
1028
1282
  function getRelativeFilePath(filePath, cwd) {
@@ -1030,11 +1284,11 @@ function getRelativeFilePath(filePath, cwd) {
1030
1284
  }
1031
1285
  async function makeCommand(target, name, cwd = process.cwd()) {
1032
1286
  const config = await loadConfig(cwd);
1033
- const appDir = join11(cwd, config.appDir);
1287
+ const appDir = join12(cwd, config.appDir);
1034
1288
  const componentName = toPascalCase2(name);
1035
1289
  switch (target) {
1036
1290
  case "page": {
1037
- const filePath = join11(appDir, name, "page.tsx");
1291
+ const filePath = join12(appDir, name, "page.tsx");
1038
1292
  writeIfNew(filePath, `// ${getRelativeFilePath(filePath, cwd)}
1039
1293
  import React from "react";
1040
1294
  import type { Metadata } from "rakta/seo";
@@ -1054,7 +1308,7 @@ export default function ${componentName}Page() {
1054
1308
  break;
1055
1309
  }
1056
1310
  case "layout": {
1057
- const filePath = join11(appDir, name, "layout.tsx");
1311
+ const filePath = join12(appDir, name, "layout.tsx");
1058
1312
  writeIfNew(filePath, `// ${getRelativeFilePath(filePath, cwd)}
1059
1313
  import React from "react";
1060
1314
  import type { LayoutProps } from "rakta/router";
@@ -1066,7 +1320,7 @@ export default function ${componentName}Layout({ children }: LayoutProps) {
1066
1320
  break;
1067
1321
  }
1068
1322
  case "component": {
1069
- const filePath = join11(cwd, "components", "ui", `${componentName}.tsx`);
1323
+ const filePath = join12(cwd, "components", "ui", `${componentName}.tsx`);
1070
1324
  writeIfNew(filePath, `// components/ui/${componentName}.tsx
1071
1325
  import React from "react";
1072
1326
 
@@ -1084,7 +1338,7 @@ export default ${componentName};
1084
1338
  break;
1085
1339
  }
1086
1340
  case "api": {
1087
- const filePath = join11(appDir, "api", name, "route.ts");
1341
+ const filePath = join12(appDir, "api", name, "route.ts");
1088
1342
  writeIfNew(filePath, `// ${getRelativeFilePath(filePath, cwd)}
1089
1343
  import type { RouteContext } from "rakta/router";
1090
1344
 
@@ -1098,23 +1352,23 @@ export async function GET(_request: Request, context: RouteContext): Promise<Res
1098
1352
  }
1099
1353
 
1100
1354
  // src/cli/routes.ts
1101
- import { join as join12 } from "path";
1355
+ import { join as join13 } from "path";
1102
1356
  async function routesCommand(cwd = process.cwd()) {
1103
1357
  const config = await loadConfig(cwd);
1104
- const appDir = join12(cwd, config.appDir);
1358
+ const appDir = join13(cwd, config.appDir);
1105
1359
  const manifest = generateManifest(appDir);
1106
1360
  printManifest(manifest);
1107
1361
  }
1108
1362
 
1109
1363
  // src/cli/rpcTypes.ts
1110
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
1111
- import { join as join13 } from "path";
1364
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "fs";
1365
+ import { join as join14 } from "path";
1112
1366
  async function rpcTypesCommand(cwd = process.cwd()) {
1113
- const sharedTypesDir = join13(cwd, "..", "shared", "types");
1114
- if (!existsSync9(sharedTypesDir)) {
1115
- mkdirSync4(sharedTypesDir, { recursive: true });
1367
+ const sharedTypesDir = join14(cwd, "..", "shared", "types");
1368
+ if (!existsSync11(sharedTypesDir)) {
1369
+ mkdirSync5(sharedTypesDir, { recursive: true });
1116
1370
  }
1117
- const outputPath = join13(sharedTypesDir, "rpc.ts");
1371
+ const outputPath = join14(sharedTypesDir, "rpc.ts");
1118
1372
  const content = `// shared/types/rpc.ts
1119
1373
  // Auto-generated by: bun rakta rpc:types
1120
1374
  // Re-exports AppRouter type from the backend for type-safe frontend RPC calls.
@@ -1122,7 +1376,7 @@ async function rpcTypesCommand(cwd = process.cwd()) {
1122
1376
 
1123
1377
  export type { AppRouter } from "../../backend/src/rpc/router.js";
1124
1378
  `;
1125
- writeFileSync4(outputPath, content, "utf-8");
1379
+ writeFileSync5(outputPath, content, "utf-8");
1126
1380
  console.log(`
1127
1381
  Generated: shared/types/rpc.ts
1128
1382
  `);
@@ -1132,16 +1386,16 @@ export type { AppRouter } from "../../backend/src/rpc/router.js";
1132
1386
  }
1133
1387
 
1134
1388
  // src/cli/seo.ts
1135
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "fs";
1136
- import { join as join14 } from "path";
1389
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
1390
+ import { join as join15 } from "path";
1137
1391
  async function seoGenerateCommand(cwd = process.cwd()) {
1138
1392
  const config = await loadConfig(cwd);
1139
- const appDir = join14(cwd, config.appDir);
1140
- const sitemapDir = join14(appDir, "api", "sitemap.xml");
1141
- const robotsDir = join14(appDir, "api", "robots.txt");
1142
- if (!existsSync10(sitemapDir)) {
1143
- mkdirSync5(sitemapDir, { recursive: true });
1144
- writeFileSync5(join14(sitemapDir, "route.ts"), `// app/api/sitemap.xml/route.ts \u2014 generated by: bun rakta seo:generate
1393
+ const appDir = join15(cwd, config.appDir);
1394
+ const sitemapDir = join15(appDir, "api", "sitemap.xml");
1395
+ const robotsDir = join15(appDir, "api", "robots.txt");
1396
+ if (!existsSync12(sitemapDir)) {
1397
+ mkdirSync6(sitemapDir, { recursive: true });
1398
+ writeFileSync6(join15(sitemapDir, "route.ts"), `// app/api/sitemap.xml/route.ts \u2014 generated by: bun rakta seo:generate
1145
1399
  import { createSitemapHandler } from "rakta/seo";
1146
1400
 
1147
1401
  export const GET = createSitemapHandler({
@@ -1156,9 +1410,9 @@ export const GET = createSitemapHandler({
1156
1410
  } else {
1157
1411
  console.warn(" Already exists: app/api/sitemap.xml/route.ts");
1158
1412
  }
1159
- if (!existsSync10(robotsDir)) {
1160
- mkdirSync5(robotsDir, { recursive: true });
1161
- writeFileSync5(join14(robotsDir, "route.ts"), `// app/api/robots.txt/route.ts \u2014 generated by: bun rakta seo:generate
1413
+ if (!existsSync12(robotsDir)) {
1414
+ mkdirSync6(robotsDir, { recursive: true });
1415
+ writeFileSync6(join15(robotsDir, "route.ts"), `// app/api/robots.txt/route.ts \u2014 generated by: bun rakta seo:generate
1162
1416
  import { createRobotsHandler } from "rakta/seo";
1163
1417
 
1164
1418
  export const GET = createRobotsHandler({
@@ -1182,11 +1436,11 @@ export const GET = createRobotsHandler({
1182
1436
  }
1183
1437
 
1184
1438
  // src/cli/start.ts
1185
- import { join as join16 } from "path";
1439
+ import { join as join17 } from "path";
1186
1440
 
1187
1441
  // src/tide/adapter.ts
1188
- import { existsSync as existsSync11, readFileSync as readFileSync3, statSync as statSync4 } from "fs";
1189
- import { join as join15 } from "path";
1442
+ import { existsSync as existsSync13, readFileSync as readFileSync3, statSync as statSync4 } from "fs";
1443
+ import { join as join16 } from "path";
1190
1444
  // src/tide/runtime.ts
1191
1445
  function createRuntimeContext(request, url, params, resolvedMode) {
1192
1446
  const searchParams = {};
@@ -1257,7 +1511,7 @@ function normalizeStaticPath(pathname) {
1257
1511
  return "index.html";
1258
1512
  }
1259
1513
  function isReadableFile2(filePath) {
1260
- return existsSync11(filePath) && statSync4(filePath).isFile();
1514
+ return existsSync13(filePath) && statSync4(filePath).isFile();
1261
1515
  }
1262
1516
  function isApiRouteExports(value) {
1263
1517
  if (typeof value !== "object" || value === null) {
@@ -1298,7 +1552,7 @@ function createBunAdapter(adapterConfig, renderConfig) {
1298
1552
  const { pathname } = url;
1299
1553
  const staticPathname = normalizeStaticPath(pathname);
1300
1554
  for (const searchDirectory of searchDirectories) {
1301
- const filePath = join15(searchDirectory, staticPathname);
1555
+ const filePath = join16(searchDirectory, staticPathname);
1302
1556
  if (isReadableFile2(filePath)) {
1303
1557
  return new Response(readFileSync3(filePath), {
1304
1558
  headers: {
@@ -1311,7 +1565,7 @@ function createBunAdapter(adapterConfig, renderConfig) {
1311
1565
  const apiRoutes = manifest.routes.filter((route) => route.kind === "api");
1312
1566
  const apiMatch = matchRoute(pathname, apiRoutes);
1313
1567
  if (apiMatch) {
1314
- const modulePath = join15(adapterConfig.appDir, apiMatch.entry.filePath);
1568
+ const modulePath = join16(adapterConfig.appDir, apiMatch.entry.filePath);
1315
1569
  const routeModule = await import(modulePath);
1316
1570
  if (!isApiRouteExports(routeModule)) {
1317
1571
  return new Response("Invalid API route module", {
@@ -1338,7 +1592,7 @@ function createBunAdapter(adapterConfig, renderConfig) {
1338
1592
  }, {
1339
1593
  appName: adapterConfig.appName,
1340
1594
  scriptPath: "/app.js",
1341
- cssPath: "/globals.css",
1595
+ cssPath: "/app.css",
1342
1596
  lang: "en"
1343
1597
  });
1344
1598
  if (renderResult.kind === "failure") {
@@ -1378,9 +1632,9 @@ async function startCommand(cwd = process.cwd()) {
1378
1632
  port: projectConfig.port,
1379
1633
  host: projectConfig.server.hostname ?? "0.0.0.0",
1380
1634
  appName: projectConfig.appName,
1381
- appDir: join16(cwd, projectConfig.appDir),
1382
- publicDir: join16(cwd, projectConfig.publicDir),
1383
- outDir: join16(cwd, outputDirectory)
1635
+ appDir: join17(cwd, projectConfig.appDir),
1636
+ publicDir: join17(cwd, projectConfig.publicDir),
1637
+ outDir: join17(cwd, outputDirectory)
1384
1638
  }, projectConfig.render);
1385
1639
  await serverAdapter.start();
1386
1640
  }
@@ -1446,7 +1700,7 @@ async function runForgeInspect() {
1446
1700
  const projectConfig = await loadConfig(cwd);
1447
1701
  const outputDirectory = projectConfig.build.outDir ?? "dist";
1448
1702
  const inspectReport = inspectBuild({
1449
- outDir: join17(cwd, outputDirectory),
1703
+ outDir: join18(cwd, outputDirectory),
1450
1704
  renderConfig: projectConfig.render
1451
1705
  });
1452
1706
  printInspectReport(inspectReport);
@@ -1514,4 +1768,4 @@ ${BOLD}${RED}Rakta.js error:${RESET} ${errorMessage}
1514
1768
  process.exit(1);
1515
1769
  });
1516
1770
 
1517
- //# debugId=E78251A4223C95A364756E2164756E21
1771
+ //# debugId=A7E4DE422B721CBF64756E2164756E21