@object-ui/cli 17.5.0 → 17.7.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.
@@ -1,9 +1,9 @@
1
1
  // src/commands/serve.ts
2
- import { createServer } from "vite";
2
+ import { createServer, createLogger } from "vite";
3
3
  import react from "@vitejs/plugin-react";
4
- import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
5
- import { join as join3, resolve, relative } from "path";
6
- import chalk2 from "chalk";
4
+ import { mkdirSync as mkdirSync2 } from "fs";
5
+ import { join as join5 } from "path";
6
+ import chalk3 from "chalk";
7
7
  import { execSync } from "child_process";
8
8
 
9
9
  // src/utils/app-generator.ts
@@ -142,7 +142,7 @@ function buildRoutedAppDependencies() {
142
142
  react: REACT_RANGE,
143
143
  "react-dom": REACT_RANGE,
144
144
  "react-router-dom": "^7.18.2",
145
- "lucide-react": "^1.29.0",
145
+ "lucide-react": "^1.43.0",
146
146
  ...Object.fromEntries(PLATFORM_RUNTIME_PACKAGES.map((name) => [name, range]))
147
147
  };
148
148
  }
@@ -536,10 +536,9 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
536
536
  let layoutWrapperEnd = "";
537
537
  if (appConfig) {
538
538
  const layoutCode = `
539
- import type { ComponentType, ReactNode } from 'react';
539
+ import type { ReactNode } from 'react';
540
540
  import { Link, useLocation } from 'react-router-dom';
541
- import * as LucideIcons from 'lucide-react';
542
- import { Moon, Sun } from "lucide-react"
541
+ import { ChevronsUpDown, Monitor, Moon, Sun } from "lucide-react"
543
542
  import { useTheme } from "./theme-provider"
544
543
  import {
545
544
  DropdownMenu,
@@ -564,7 +563,9 @@ import {
564
563
  Separator,
565
564
  Collapsible,
566
565
  CollapsibleTrigger,
567
- CollapsibleContent
566
+ CollapsibleContent,
567
+ LazyIcon,
568
+ isLucideIconName
568
569
  } from '@object-ui/components';
569
570
 
570
571
  /** One entry of \`app.json\`'s \`menu\`, as this layout reads it. */
@@ -582,21 +583,20 @@ type AppConfig = {
582
583
  menu?: MenuItem[];
583
584
  };
584
585
 
585
- // Lucide publishes every icon as a named export, and a menu entry names one as
586
- // a string \u2014 so the lookup is a runtime index into the namespace object, which
587
- // has no index signature. Narrowing it to the component-by-name shape this file
588
- // actually uses keeps that honest without an \`any\` or a \`@ts-expect-error\`; the
589
- // \`undefined\` arm is real, since the namespace also exports helpers that are not
590
- // components and a schema may name an icon that does not exist.
591
- const lucideIcons = LucideIcons as unknown as Record<
592
- string,
593
- ComponentType<{ className?: string }> | undefined
594
- >;
595
-
586
+ // An authored \`icon\` name is resolved by the platform seam
587
+ // (\`@object-ui/components\`), never by a lookup this template rolls itself.
588
+ // That is objectui#5935's ruling \u2014 one tokeniser and one icon-name vocabulary
589
+ // for every container \u2014 and this generated layout is a container like any
590
+ // other, even though it runs in the user's app rather than in this repo.
591
+ //
592
+ // \`isLucideIconName\` is asked FIRST because this call site has a better
593
+ // fallback than the seam's: a sidebar entry with an unresolvable icon renders
594
+ // no glyph at all, where \`LazyIcon\` alone would substitute a stray database
595
+ // icon. The seam exports the predicate for exactly this ("ask first, then
596
+ // choose"), so preferring it costs no second vocabulary.
596
597
  const DynamicIcon = ({ name, className }: { name: string; className?: string }) => {
597
- const Icon = lucideIcons[name];
598
- if (!Icon) return null;
599
- return <Icon className={className} />;
598
+ if (!isLucideIconName(name)) return null;
599
+ return <LazyIcon name={name} className={className} />;
600
600
  };
601
601
 
602
602
  export function ModeToggle() {
@@ -614,20 +614,20 @@ export function ModeToggle() {
614
614
  <span className="truncate font-semibold">Switch Theme</span>
615
615
  <span className="truncate text-xs">Light / Dark</span>
616
616
  </div>
617
- <LucideIcons.ChevronsUpDown className="ml-auto size-4" />
617
+ <ChevronsUpDown className="ml-auto size-4" />
618
618
  </SidebarMenuButton>
619
619
  </DropdownMenuTrigger>
620
620
  <DropdownMenuContent className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg" side="bottom" align="end" sideOffset={4}>
621
621
  <DropdownMenuItem onClick={() => setTheme("light")}>
622
- <LucideIcons.Sun className="mr-2 size-4" />
622
+ <Sun className="mr-2 size-4" />
623
623
  Light
624
624
  </DropdownMenuItem>
625
625
  <DropdownMenuItem onClick={() => setTheme("dark")}>
626
- <LucideIcons.Moon className="mr-2 size-4" />
626
+ <Moon className="mr-2 size-4" />
627
627
  Dark
628
628
  </DropdownMenuItem>
629
629
  <DropdownMenuItem onClick={() => setTheme("system")}>
630
- <LucideIcons.Monitor className="mr-2 size-4" />
630
+ <Monitor className="mr-2 size-4" />
631
631
  System
632
632
  </DropdownMenuItem>
633
633
  </DropdownMenuContent>
@@ -778,66 +778,304 @@ export default App;`;
778
778
  return files;
779
779
  }
780
780
 
781
- // src/commands/serve.ts
782
- async function serve(schemaPath, options) {
783
- const cwd = process.cwd();
784
- const pagesDir = join3(cwd, "pages");
785
- const hasPagesDir = existsSync3(pagesDir);
786
- let routes = [];
787
- let schema = null;
788
- let useFileSystemRouting = false;
789
- if (hasPagesDir) {
790
- console.log(chalk2.blue("\u{1F4C1} Detected pages/ directory - using file-system routing"));
791
- routes = scanPagesDirectory(pagesDir);
792
- useFileSystemRouting = true;
793
- if (routes.length === 0) {
794
- throw new Error("No schema files found in pages/ directory");
795
- }
796
- console.log(chalk2.green(`\u2713 Found ${routes.length} route(s)`));
797
- routes.forEach((route) => {
798
- console.log(chalk2.dim(` ${route.path} \u2192 ${relative(cwd, route.filePath)}`));
799
- });
800
- } else {
801
- const fullSchemaPath = resolve(cwd, schemaPath);
802
- if (!existsSync3(fullSchemaPath)) {
803
- throw new Error(`Schema file not found: ${schemaPath}
804
- Run 'objectui init' to create a sample schema.`);
781
+ // src/utils/project-source.ts
782
+ import { existsSync as existsSync3, statSync as statSync2 } from "fs";
783
+ import { basename, dirname as dirname3, join as join3, relative, resolve } from "path";
784
+ import chalk2 from "chalk";
785
+ function readAppConfig(path, warnings) {
786
+ try {
787
+ return parseSchemaFile(path);
788
+ } catch (error) {
789
+ warnings.push(
790
+ `Failed to parse app config ${path}: ${error instanceof Error ? error.message : error}`
791
+ );
792
+ return null;
793
+ }
794
+ }
795
+ function resolveProjectSource(cwd, schemaArg) {
796
+ const warnings = [];
797
+ const absoluteSchemaPath = resolve(cwd, schemaArg);
798
+ if (existsSync3(absoluteSchemaPath)) {
799
+ const argumentStats = statSync2(absoluteSchemaPath);
800
+ if (argumentStats.isFile()) {
801
+ const projectRoot = dirname3(absoluteSchemaPath);
802
+ const pagesDir = join3(projectRoot, "pages");
803
+ if (existsSync3(pagesDir)) {
804
+ return {
805
+ mode: "routes",
806
+ projectRoot,
807
+ pagesDir,
808
+ pagesDirOrigin: "schema-dir",
809
+ routes: scanRoutes(pagesDir),
810
+ appConfig: readAppConfig(absoluteSchemaPath, warnings),
811
+ appConfigPath: absoluteSchemaPath,
812
+ warnings
813
+ };
814
+ }
815
+ } else if (argumentStats.isDirectory()) {
816
+ const fromDirectory = resolveDirectoryArgument(absoluteSchemaPath, warnings);
817
+ if (fromDirectory) return fromDirectory;
805
818
  }
806
- console.log(chalk2.blue("\u{1F4CB} Loading schema:"), chalk2.cyan(schemaPath));
819
+ }
820
+ const localPagesDir = join3(cwd, "pages");
821
+ if (existsSync3(localPagesDir)) {
822
+ const localAppConfigPath = join3(cwd, "app.json");
823
+ const hasLocalAppConfig = existsSync3(localAppConfigPath);
824
+ return {
825
+ mode: "routes",
826
+ projectRoot: cwd,
827
+ pagesDir: localPagesDir,
828
+ pagesDirOrigin: "cwd",
829
+ routes: scanRoutes(localPagesDir),
830
+ appConfig: hasLocalAppConfig ? readAppConfig(localAppConfigPath, warnings) : null,
831
+ appConfigPath: hasLocalAppConfig ? localAppConfigPath : null,
832
+ warnings
833
+ };
834
+ }
835
+ if (!existsSync3(absoluteSchemaPath)) {
836
+ throw new Error(
837
+ `Schema file not found: ${schemaArg}
838
+ Run 'objectui init' to create a sample schema.`
839
+ );
840
+ }
841
+ if (statSync2(absoluteSchemaPath).isDirectory()) {
842
+ throw new Error(
843
+ `Not a project directory: ${schemaArg}
844
+ A directory argument must be a 'pages' directory, or contain one, for file-system routing \u2014 ${absoluteSchemaPath} is neither.
845
+ Pass a JSON/YAML schema file instead, or run 'objectui init' to create a project.`
846
+ );
847
+ }
848
+ let schema;
849
+ try {
850
+ schema = parseSchemaFile(absoluteSchemaPath);
851
+ } catch (error) {
852
+ throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);
853
+ }
854
+ return {
855
+ mode: "schema",
856
+ projectRoot: dirname3(absoluteSchemaPath),
857
+ schemaFile: absoluteSchemaPath,
858
+ schema,
859
+ warnings
860
+ };
861
+ }
862
+ function resolveDirectoryArgument(argumentDir, warnings) {
863
+ const isPagesDir = basename(argumentDir) === "pages";
864
+ const pagesDir = isPagesDir ? argumentDir : join3(argumentDir, "pages");
865
+ if (!isPagesDir && !(existsSync3(pagesDir) && statSync2(pagesDir).isDirectory())) {
866
+ return null;
867
+ }
868
+ const projectRoot = isPagesDir ? dirname3(argumentDir) : argumentDir;
869
+ const appConfigPath = join3(projectRoot, "app.json");
870
+ const hasAppConfig = existsSync3(appConfigPath) && statSync2(appConfigPath).isFile();
871
+ return {
872
+ mode: "routes",
873
+ projectRoot,
874
+ pagesDir,
875
+ pagesDirOrigin: "argument-dir",
876
+ routes: scanRoutes(pagesDir),
877
+ appConfig: hasAppConfig ? readAppConfig(appConfigPath, warnings) : null,
878
+ appConfigPath: hasAppConfig ? appConfigPath : null,
879
+ warnings
880
+ };
881
+ }
882
+ function scanRoutes(pagesDir) {
883
+ const routes = scanPagesDirectory(pagesDir);
884
+ if (routes.length === 0) {
885
+ throw new Error(`No schema files found in ${pagesDir}`);
886
+ }
887
+ return routes;
888
+ }
889
+ function reportProjectSource(source, cwd) {
890
+ for (const warning of source.warnings) {
891
+ console.warn(chalk2.yellow(`\u26A0 ${warning}`));
892
+ }
893
+ if (source.mode === "schema") {
894
+ console.log(chalk2.blue("\u{1F4CB} Loading schema:"), chalk2.cyan(relative(cwd, source.schemaFile) || source.schemaFile));
895
+ return;
896
+ }
897
+ console.log(chalk2.blue(`\u{1F4C2} Detected project structure at ${source.projectRoot}`));
898
+ if (source.appConfigPath && source.appConfig) {
899
+ console.log(chalk2.blue(`\u2699\uFE0F Loaded App Config from ${relative(cwd, source.appConfigPath) || source.appConfigPath}`));
900
+ }
901
+ console.log(chalk2.blue(`\u{1F4C1} Using file-system routing from ${source.pagesDir}`));
902
+ console.log(chalk2.green(`\u2713 Found ${source.routes.length} route(s)`));
903
+ for (const route of source.routes) {
904
+ console.log(chalk2.dim(` ${route.path} \u2192 ${relative(cwd, route.filePath)}`));
905
+ }
906
+ }
907
+
908
+ // src/utils/workspace-vite.ts
909
+ import { existsSync as existsSync4, readFileSync as readFileSync3, statSync as statSync3, unlinkSync } from "fs";
910
+ import { createRequire } from "module";
911
+ import { dirname as dirname4, join as join4 } from "path";
912
+ import { globSync } from "glob";
913
+ import { load as loadYaml } from "js-yaml";
914
+ var PLATFORM_SCOPE = "@object-ui/";
915
+ var BARREL_EXTENSIONS = [".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx"];
916
+ function isWorkspaceRoot(cwd) {
917
+ return existsSync4(join4(cwd, "pnpm-workspace.yaml"));
918
+ }
919
+ function workspacePatterns(cwd) {
920
+ const manifestPath = join4(cwd, "pnpm-workspace.yaml");
921
+ if (!existsSync4(manifestPath)) return [];
922
+ const parsed = loadYaml(readFileSync3(manifestPath, "utf-8"));
923
+ const patterns = parsed?.packages;
924
+ if (!Array.isArray(patterns)) return [];
925
+ return patterns.filter((p) => typeof p === "string");
926
+ }
927
+ function workspacePackageDirs(cwd) {
928
+ const patterns = workspacePatterns(cwd);
929
+ const include = patterns.filter((p) => !p.startsWith("!"));
930
+ const exclude = patterns.filter((p) => p.startsWith("!")).map((p) => p.slice(1));
931
+ if (include.length === 0) return [];
932
+ const matches = globSync(include, {
933
+ cwd,
934
+ absolute: true,
935
+ ignore: ["**/node_modules/**", ...exclude]
936
+ });
937
+ return matches.filter((dir) => existsSync4(join4(dir, "package.json")) && statSync3(dir).isDirectory()).sort();
938
+ }
939
+ function findSourceBarrel(srcDir) {
940
+ for (const ext of BARREL_EXTENSIONS) {
941
+ const candidate = join4(srcDir, `index${ext}`);
942
+ if (existsSync4(candidate)) return candidate;
943
+ }
944
+ return void 0;
945
+ }
946
+ function workspaceSourceAliases(cwd) {
947
+ const aliases = {};
948
+ for (const dir of workspacePackageDirs(cwd)) {
949
+ let name;
807
950
  try {
808
- schema = parseSchemaFile(fullSchemaPath);
809
- } catch (error) {
810
- throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);
951
+ name = JSON.parse(readFileSync3(join4(dir, "package.json"), "utf-8")).name;
952
+ } catch {
953
+ continue;
811
954
  }
955
+ if (typeof name !== "string" || !name.startsWith(PLATFORM_SCOPE)) continue;
956
+ const srcDir = join4(dir, "src");
957
+ if (!existsSync4(srcDir) || !findSourceBarrel(srcDir)) continue;
958
+ aliases[name] = srcDir;
959
+ }
960
+ return aliases;
961
+ }
962
+ function resolveLucideAlias(cwd) {
963
+ const require2 = createRequire(join4(cwd, "package.json"));
964
+ try {
965
+ return dirname4(require2.resolve("lucide-react/package.json", { paths: [join4(cwd, "packages/components")] }));
966
+ } catch {
967
+ return void 0;
968
+ }
969
+ }
970
+ async function loadTempAppPostcssPlugins() {
971
+ try {
972
+ const [tailwindPostcss, autoprefixer] = await Promise.all([
973
+ import("@tailwindcss/postcss"),
974
+ import("autoprefixer")
975
+ ]);
976
+ return [tailwindPostcss.default(), autoprefixer.default()];
977
+ } catch (error) {
978
+ throw new Error(
979
+ `Failed to load the Tailwind CSS PostCSS pipeline: ${error instanceof Error ? error.message : error}
980
+ Both '@tailwindcss/postcss' and 'autoprefixer' are dependencies of @object-ui/cli \u2014 a
981
+ broken install of the CLI is the likeliest cause; reinstall it and try again.
982
+ (Refusing to start unstyled: that failure is silent in the browser.)`
983
+ );
984
+ }
985
+ }
986
+ async function prepareWorkspaceTempApp(cwd, tmpDir) {
987
+ const postcssPath = join4(tmpDir, "postcss.config.js");
988
+ if (existsSync4(postcssPath)) {
989
+ unlinkSync(postcssPath);
990
+ }
991
+ const alias = { ...workspaceSourceAliases(cwd) };
992
+ const lucide = resolveLucideAlias(cwd);
993
+ if (lucide) {
994
+ alias["lucide-react"] = lucide;
812
995
  }
813
- const tmpDir = join3(cwd, ".objectui-tmp");
996
+ return {
997
+ resolve: { alias },
998
+ css: { postcss: { plugins: await loadTempAppPostcssPlugins() } }
999
+ };
1000
+ }
1001
+
1002
+ // src/commands/serve.ts
1003
+ function resolveServeOpenOption(open) {
1004
+ return open !== false;
1005
+ }
1006
+ var BROWSER_OPEN_SPAWN_ENOENT = /^Error: spawn (\S+) ENOENT/;
1007
+ function createServeLogger(base) {
1008
+ return {
1009
+ info: (msg, opts) => base.info(msg, opts),
1010
+ warn: (msg, opts) => base.warn(msg, opts),
1011
+ warnOnce: (msg, opts) => base.warnOnce(msg, opts),
1012
+ error(msg, opts) {
1013
+ const match = BROWSER_OPEN_SPAWN_ENOENT.exec(msg);
1014
+ if (match) {
1015
+ const [, command] = match;
1016
+ console.log(
1017
+ chalk3.dim(
1018
+ ` (could not open the browser automatically \u2014 '${command}' is not available in this environment; open the URL above manually)`
1019
+ )
1020
+ );
1021
+ return;
1022
+ }
1023
+ base.error(msg, opts);
1024
+ },
1025
+ clearScreen: (type) => base.clearScreen(type),
1026
+ hasErrorLogged: (error) => base.hasErrorLogged(error),
1027
+ get hasWarned() {
1028
+ return base.hasWarned;
1029
+ }
1030
+ };
1031
+ }
1032
+ async function serve(schemaPath, options) {
1033
+ const cwd = process.cwd();
1034
+ const source = resolveProjectSource(cwd, schemaPath);
1035
+ reportProjectSource(source, cwd);
1036
+ const tmpDir = join5(cwd, ".objectui-tmp");
814
1037
  mkdirSync2(tmpDir, { recursive: true });
815
- if (useFileSystemRouting) {
816
- createTempAppWithRouting(tmpDir, routes);
1038
+ if (source.mode === "routes") {
1039
+ createTempAppWithRouting(tmpDir, source.routes, source.appConfig);
817
1040
  } else {
818
- createTempApp(tmpDir, schema);
1041
+ createTempApp(tmpDir, source.schema);
819
1042
  }
820
- console.log(chalk2.blue("\u{1F4E6} Installing dependencies..."));
821
- console.log(chalk2.dim(" This may take a moment on first run..."));
822
- try {
823
- execSync("npm install --silent --prefer-offline", {
824
- cwd: tmpDir,
825
- stdio: "inherit"
826
- });
827
- console.log(chalk2.green("\u2713 Dependencies installed"));
828
- } catch {
829
- throw new Error("Failed to install dependencies. Please check your internet connection and try again.");
1043
+ const isMonorepo = isWorkspaceRoot(cwd);
1044
+ if (isMonorepo) {
1045
+ console.log(chalk3.blue("\u{1F4E6} Detected monorepo - using root node_modules"));
1046
+ } else {
1047
+ console.log(chalk3.blue("\u{1F4E6} Installing dependencies..."));
1048
+ console.log(chalk3.dim(" This may take a moment on first run..."));
1049
+ try {
1050
+ execSync("npm install --silent --prefer-offline", {
1051
+ cwd: tmpDir,
1052
+ stdio: "inherit"
1053
+ });
1054
+ console.log(chalk3.green("\u2713 Dependencies installed"));
1055
+ } catch {
1056
+ throw new Error("Failed to install dependencies. Please check your internet connection and try again.");
1057
+ }
1058
+ }
1059
+ console.log(chalk3.green("\u2713 Schema loaded successfully"));
1060
+ console.log(chalk3.blue("\u{1F680} Starting development server...\n"));
1061
+ if (isMonorepo) {
1062
+ console.log(chalk3.blue("\u{1F4E6} Detected monorepo - configuring workspace aliases"));
830
1063
  }
831
- console.log(chalk2.green("\u2713 Schema loaded successfully"));
832
- console.log(chalk2.blue("\u{1F680} Starting development server...\n"));
1064
+ const workspaceConfig = isMonorepo ? await prepareWorkspaceTempApp(cwd, tmpDir) : {};
833
1065
  const viteConfig = {
834
1066
  root: tmpDir,
835
1067
  server: {
836
1068
  port: parseInt(options.port),
837
1069
  host: options.host,
838
- open: true
1070
+ open: resolveServeOpenOption(options.open),
1071
+ fs: {
1072
+ // Allow serving the workspace sources the aliases point at
1073
+ allow: [cwd]
1074
+ }
839
1075
  },
840
- plugins: [react()]
1076
+ plugins: [react()],
1077
+ customLogger: createServeLogger(createLogger()),
1078
+ ...workspaceConfig
841
1079
  };
842
1080
  const server = await createServer(viteConfig);
843
1081
  await server.listen();
@@ -845,31 +1083,31 @@ Run 'objectui init' to create a sample schema.`);
845
1083
  const protocol = server.config.server.https ? "https" : "http";
846
1084
  const displayHost = host === "0.0.0.0" ? "localhost" : host;
847
1085
  console.log();
848
- console.log(chalk2.green("\u2713 Server started successfully!"));
1086
+ console.log(chalk3.green("\u2713 Server started successfully!"));
849
1087
  console.log();
850
- console.log(chalk2.bold(" Local: ") + chalk2.cyan(`${protocol}://${displayHost}:${port}`));
1088
+ console.log(chalk3.bold(" Local: ") + chalk3.cyan(`${protocol}://${displayHost}:${port}`));
851
1089
  console.log();
852
- console.log(chalk2.dim(" Press Ctrl+C to stop the server"));
1090
+ console.log(chalk3.dim(" Press Ctrl+C to stop the server"));
853
1091
  console.log();
854
1092
  }
855
1093
 
856
1094
  // src/commands/init.ts
857
- import { existsSync as existsSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
858
- import { dirname as dirname3, join as join4 } from "path";
859
- import chalk3 from "chalk";
1095
+ import { existsSync as existsSync5, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
1096
+ import { dirname as dirname5, join as join6 } from "path";
1097
+ import chalk4 from "chalk";
860
1098
  var templates = {
861
1099
  simple: {
862
1100
  type: "div",
863
1101
  className: "min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100",
864
- body: {
1102
+ children: {
865
1103
  type: "card",
866
1104
  className: "w-full max-w-md shadow-lg",
867
1105
  title: "Welcome to Object UI",
868
1106
  description: "Start building your application with JSON schemas",
869
- body: {
1107
+ children: {
870
1108
  type: "div",
871
1109
  className: "p-6 space-y-4",
872
- body: [
1110
+ children: [
873
1111
  {
874
1112
  type: "text",
875
1113
  content: "This is a simple example. Edit app.json to customize your application.",
@@ -887,19 +1125,19 @@ var templates = {
887
1125
  form: {
888
1126
  type: "div",
889
1127
  className: "min-h-screen flex items-center justify-center bg-gradient-to-br from-purple-50 to-pink-100 p-4",
890
- body: {
1128
+ children: {
891
1129
  type: "card",
892
1130
  className: "w-full max-w-2xl shadow-xl",
893
1131
  title: "Contact Form",
894
1132
  description: "Fill out the form below to get in touch",
895
- body: {
1133
+ children: {
896
1134
  type: "div",
897
1135
  className: "p-6 space-y-6",
898
- body: [
1136
+ children: [
899
1137
  {
900
1138
  type: "div",
901
1139
  className: "grid grid-cols-2 gap-4",
902
- body: [
1140
+ children: [
903
1141
  {
904
1142
  type: "input",
905
1143
  label: "First Name",
@@ -936,7 +1174,7 @@ var templates = {
936
1174
  {
937
1175
  type: "div",
938
1176
  className: "flex gap-3",
939
- body: [
1177
+ children: [
940
1178
  {
941
1179
  type: "button",
942
1180
  label: "Submit",
@@ -957,21 +1195,21 @@ var templates = {
957
1195
  dashboard: {
958
1196
  type: "div",
959
1197
  className: "min-h-screen bg-muted/10",
960
- body: [
1198
+ children: [
961
1199
  {
962
1200
  type: "div",
963
1201
  className: "border-b bg-background",
964
- body: {
1202
+ children: {
965
1203
  type: "div",
966
1204
  className: "container mx-auto px-6 py-4",
967
- body: {
1205
+ children: {
968
1206
  type: "div",
969
1207
  className: "flex items-center justify-between",
970
- body: [
1208
+ children: [
971
1209
  {
972
1210
  type: "div",
973
1211
  className: "text-2xl font-bold",
974
- body: { type: "text", content: "Dashboard" }
1212
+ children: { type: "text", content: "Dashboard" }
975
1213
  },
976
1214
  {
977
1215
  type: "button",
@@ -985,37 +1223,37 @@ var templates = {
985
1223
  {
986
1224
  type: "div",
987
1225
  className: "container mx-auto p-6 space-y-6",
988
- body: [
1226
+ children: [
989
1227
  {
990
1228
  type: "div",
991
1229
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
992
- body: [
1230
+ children: [
993
1231
  {
994
1232
  type: "card",
995
1233
  className: "shadow-sm",
996
- body: [
1234
+ children: [
997
1235
  {
998
1236
  type: "div",
999
1237
  className: "p-6 pb-2",
1000
- body: {
1238
+ children: {
1001
1239
  type: "div",
1002
1240
  className: "text-sm font-medium text-muted-foreground",
1003
- body: { type: "text", content: "Total Revenue" }
1241
+ children: { type: "text", content: "Total Revenue" }
1004
1242
  }
1005
1243
  },
1006
1244
  {
1007
1245
  type: "div",
1008
1246
  className: "p-6 pt-0",
1009
- body: [
1247
+ children: [
1010
1248
  {
1011
1249
  type: "div",
1012
1250
  className: "text-2xl font-bold",
1013
- body: { type: "text", content: "$45,231.89" }
1251
+ children: { type: "text", content: "$45,231.89" }
1014
1252
  },
1015
1253
  {
1016
1254
  type: "div",
1017
1255
  className: "text-xs text-muted-foreground mt-1",
1018
- body: { type: "text", content: "+20.1% from last month" }
1256
+ children: { type: "text", content: "+20.1% from last month" }
1019
1257
  }
1020
1258
  ]
1021
1259
  }
@@ -1024,29 +1262,29 @@ var templates = {
1024
1262
  {
1025
1263
  type: "card",
1026
1264
  className: "shadow-sm",
1027
- body: [
1265
+ children: [
1028
1266
  {
1029
1267
  type: "div",
1030
1268
  className: "p-6 pb-2",
1031
- body: {
1269
+ children: {
1032
1270
  type: "div",
1033
1271
  className: "text-sm font-medium text-muted-foreground",
1034
- body: { type: "text", content: "Active Users" }
1272
+ children: { type: "text", content: "Active Users" }
1035
1273
  }
1036
1274
  },
1037
1275
  {
1038
1276
  type: "div",
1039
1277
  className: "p-6 pt-0",
1040
- body: [
1278
+ children: [
1041
1279
  {
1042
1280
  type: "div",
1043
1281
  className: "text-2xl font-bold",
1044
- body: { type: "text", content: "+2,350" }
1282
+ children: { type: "text", content: "+2,350" }
1045
1283
  },
1046
1284
  {
1047
1285
  type: "div",
1048
1286
  className: "text-xs text-muted-foreground mt-1",
1049
- body: { type: "text", content: "+180.1% from last month" }
1287
+ children: { type: "text", content: "+180.1% from last month" }
1050
1288
  }
1051
1289
  ]
1052
1290
  }
@@ -1055,29 +1293,29 @@ var templates = {
1055
1293
  {
1056
1294
  type: "card",
1057
1295
  className: "shadow-sm",
1058
- body: [
1296
+ children: [
1059
1297
  {
1060
1298
  type: "div",
1061
1299
  className: "p-6 pb-2",
1062
- body: {
1300
+ children: {
1063
1301
  type: "div",
1064
1302
  className: "text-sm font-medium text-muted-foreground",
1065
- body: { type: "text", content: "Sales" }
1303
+ children: { type: "text", content: "Sales" }
1066
1304
  }
1067
1305
  },
1068
1306
  {
1069
1307
  type: "div",
1070
1308
  className: "p-6 pt-0",
1071
- body: [
1309
+ children: [
1072
1310
  {
1073
1311
  type: "div",
1074
1312
  className: "text-2xl font-bold",
1075
- body: { type: "text", content: "+12,234" }
1313
+ children: { type: "text", content: "+12,234" }
1076
1314
  },
1077
1315
  {
1078
1316
  type: "div",
1079
1317
  className: "text-xs text-muted-foreground mt-1",
1080
- body: { type: "text", content: "+19% from last month" }
1318
+ children: { type: "text", content: "+19% from last month" }
1081
1319
  }
1082
1320
  ]
1083
1321
  }
@@ -1086,29 +1324,29 @@ var templates = {
1086
1324
  {
1087
1325
  type: "card",
1088
1326
  className: "shadow-sm",
1089
- body: [
1327
+ children: [
1090
1328
  {
1091
1329
  type: "div",
1092
1330
  className: "p-6 pb-2",
1093
- body: {
1331
+ children: {
1094
1332
  type: "div",
1095
1333
  className: "text-sm font-medium text-muted-foreground",
1096
- body: { type: "text", content: "Active Now" }
1334
+ children: { type: "text", content: "Active Now" }
1097
1335
  }
1098
1336
  },
1099
1337
  {
1100
1338
  type: "div",
1101
1339
  className: "p-6 pt-0",
1102
- body: [
1340
+ children: [
1103
1341
  {
1104
1342
  type: "div",
1105
1343
  className: "text-2xl font-bold",
1106
- body: { type: "text", content: "+573" }
1344
+ children: { type: "text", content: "+573" }
1107
1345
  },
1108
1346
  {
1109
1347
  type: "div",
1110
1348
  className: "text-xs text-muted-foreground mt-1",
1111
- body: { type: "text", content: "+201 since last hour" }
1349
+ children: { type: "text", content: "+201 since last hour" }
1112
1350
  }
1113
1351
  ]
1114
1352
  }
@@ -1121,27 +1359,27 @@ var templates = {
1121
1359
  className: "shadow-sm",
1122
1360
  title: "Recent Activity",
1123
1361
  description: "Your latest updates and notifications",
1124
- body: {
1362
+ children: {
1125
1363
  type: "div",
1126
1364
  className: "p-6 pt-0 space-y-4",
1127
- body: [
1365
+ children: [
1128
1366
  {
1129
1367
  type: "div",
1130
1368
  className: "flex items-center gap-4 border-b pb-4",
1131
- body: [
1369
+ children: [
1132
1370
  {
1133
1371
  type: "div",
1134
1372
  className: "flex-1",
1135
- body: [
1373
+ children: [
1136
1374
  {
1137
1375
  type: "div",
1138
1376
  className: "font-medium",
1139
- body: { type: "text", content: "New user registration" }
1377
+ children: { type: "text", content: "New user registration" }
1140
1378
  },
1141
1379
  {
1142
1380
  type: "div",
1143
1381
  className: "text-sm text-muted-foreground",
1144
- body: { type: "text", content: "2 minutes ago" }
1382
+ children: { type: "text", content: "2 minutes ago" }
1145
1383
  }
1146
1384
  ]
1147
1385
  }
@@ -1150,20 +1388,20 @@ var templates = {
1150
1388
  {
1151
1389
  type: "div",
1152
1390
  className: "flex items-center gap-4 border-b pb-4",
1153
- body: [
1391
+ children: [
1154
1392
  {
1155
1393
  type: "div",
1156
1394
  className: "flex-1",
1157
- body: [
1395
+ children: [
1158
1396
  {
1159
1397
  type: "div",
1160
1398
  className: "font-medium",
1161
- body: { type: "text", content: "Payment received" }
1399
+ children: { type: "text", content: "Payment received" }
1162
1400
  },
1163
1401
  {
1164
1402
  type: "div",
1165
1403
  className: "text-sm text-muted-foreground",
1166
- body: { type: "text", content: "15 minutes ago" }
1404
+ children: { type: "text", content: "15 minutes ago" }
1167
1405
  }
1168
1406
  ]
1169
1407
  }
@@ -1172,20 +1410,20 @@ var templates = {
1172
1410
  {
1173
1411
  type: "div",
1174
1412
  className: "flex items-center gap-4",
1175
- body: [
1413
+ children: [
1176
1414
  {
1177
1415
  type: "div",
1178
1416
  className: "flex-1",
1179
- body: [
1417
+ children: [
1180
1418
  {
1181
1419
  type: "div",
1182
1420
  className: "font-medium",
1183
- body: { type: "text", content: "New order placed" }
1421
+ children: { type: "text", content: "New order placed" }
1184
1422
  },
1185
1423
  {
1186
1424
  type: "div",
1187
1425
  className: "text-sm text-muted-foreground",
1188
- body: { type: "text", content: "1 hour ago" }
1426
+ children: { type: "text", content: "1 hour ago" }
1189
1427
  }
1190
1428
  ]
1191
1429
  }
@@ -1370,46 +1608,47 @@ export default function App() {
1370
1608
  }
1371
1609
  async function init(name, options) {
1372
1610
  const cwd = process.cwd();
1373
- const projectDir = join4(cwd, name);
1374
- if (existsSync4(projectDir) && name !== ".") {
1611
+ const projectDir = join6(cwd, name);
1612
+ if (existsSync5(projectDir) && name !== ".") {
1375
1613
  throw new Error(`Directory "${name}" already exists. Please choose a different name.`);
1376
1614
  }
1377
1615
  const targetDir = name === "." ? cwd : projectDir;
1616
+ const files = buildInitFiles(name, options.template);
1378
1617
  if (name !== ".") {
1379
1618
  mkdirSync3(projectDir, { recursive: true });
1380
1619
  }
1381
- console.log(chalk3.blue("\u{1F3A8} Creating Object UI application..."));
1382
- console.log(chalk3.dim(` Template: ${options.template}`));
1620
+ console.log(chalk4.blue("\u{1F3A8} Creating Object UI application..."));
1621
+ console.log(chalk4.dim(` Template: ${options.template}`));
1383
1622
  console.log();
1384
- for (const [relativePath, contents] of Object.entries(
1385
- buildInitFiles(name, options.template)
1386
- )) {
1387
- const target = join4(targetDir, relativePath);
1388
- mkdirSync3(dirname3(target), { recursive: true });
1623
+ for (const [relativePath, contents] of Object.entries(files)) {
1624
+ const target = join6(targetDir, relativePath);
1625
+ mkdirSync3(dirname5(target), { recursive: true });
1389
1626
  writeFileSync2(target, contents);
1390
- console.log(chalk3.green(`\u2713 Created ${relativePath}`));
1627
+ console.log(chalk4.green(`\u2713 Created ${relativePath}`));
1391
1628
  }
1392
1629
  console.log();
1393
- console.log(chalk3.green("\u2728 Application created successfully!"));
1630
+ console.log(chalk4.green("\u2728 Application created successfully!"));
1394
1631
  console.log();
1395
- console.log(chalk3.bold("Next steps:"));
1632
+ console.log(chalk4.bold("Next steps:"));
1396
1633
  console.log();
1397
1634
  if (name !== ".") {
1398
- console.log(chalk3.cyan(` cd ${name}`));
1635
+ console.log(chalk4.cyan(` cd ${name}`));
1399
1636
  }
1400
- console.log(chalk3.cyan(" npm install"));
1401
- console.log(chalk3.cyan(" npm run dev"));
1637
+ console.log(chalk4.cyan(" npm install"));
1638
+ console.log(chalk4.cyan(" npm run dev"));
1402
1639
  console.log();
1403
- console.log(chalk3.dim(" The development server will start on http://localhost:3000"));
1640
+ console.log(chalk4.dim(" The development server will start on http://localhost:3000"));
1404
1641
  console.log();
1405
1642
  }
1406
1643
 
1407
1644
  export {
1408
- parseSchemaFile,
1409
- scanPagesDirectory,
1410
1645
  createTempApp,
1411
1646
  createTempAppWithRouting,
1647
+ resolveProjectSource,
1648
+ reportProjectSource,
1649
+ isWorkspaceRoot,
1650
+ prepareWorkspaceTempApp,
1412
1651
  serve,
1413
1652
  init
1414
1653
  };
1415
- //# sourceMappingURL=chunk-2MZA766D.js.map
1654
+ //# sourceMappingURL=chunk-VMMIGYU3.js.map