@object-ui/cli 17.6.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @object-ui/cli
2
2
 
3
- > Standalone CLI for **Object UI** — scaffold, develop, build, lint, test and validate
3
+ > Standalone CLI for **Object UI** — scaffold, develop, build and validate
4
4
  > JSON/YAML schema-driven applications.
5
5
 
6
6
  ```bash
@@ -87,37 +87,27 @@ objectui start --port 8080 --dir build
87
87
 
88
88
  Legacy alias of `dev` (kept for older scripts).
89
89
 
90
- ### `objectui lint`
91
-
92
- Lint the generated application code via ESLint.
93
-
94
- ```bash
95
- objectui lint --fix
96
- ```
97
-
98
- ### `objectui test`
99
-
100
- Run the application's tests via Vitest.
101
-
102
- ```bash
103
- objectui test --watch
104
- objectui test --coverage
105
- objectui test --ui
106
- ```
107
-
108
90
  ### `objectui generate <type> <name>` (alias `g`)
109
91
 
110
92
  Generate new resources (`resource`/`object`, `page`, `plugin`).
111
93
 
112
- ### `objectui add <component>`
113
-
114
- Add a new component renderer to your project.
115
-
116
94
  ### `objectui validate [schema]`
117
95
 
118
96
  Validate a schema file against the ObjectUI specification.
119
97
 
120
- ### `objectui check`, `objectui doctor`, `objectui studio`, `objectui analyze`, `objectui create plugin <name>`
98
+ The document is judged through the strict authoring face: a key no schema
99
+ declares is refused, at any depth, and each one is named with the path of the
100
+ object carrying it and what to do — remove it, or check its spelling against
101
+ the keys declared at that position.
102
+
103
+ A failure is reported at the document root and then narrowed to the union arm
104
+ your `type` selected — the `1.1`-style entries under a numbered issue are that
105
+ arm's own diagnosis, at the real path of the node that failed. When no component
106
+ type matches, the report names the nearest few of the accepted values instead of
107
+ listing all of them. See the
108
+ [docs](https://www.objectui.org/docs/utilities/cli) for worked output.
109
+
110
+ ### `objectui check`, `objectui doctor`, `objectui analyze`
121
111
 
122
112
  Utility commands — see `objectui --help`.
123
113
 
@@ -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.31.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>
@@ -1099,15 +1099,15 @@ var templates = {
1099
1099
  simple: {
1100
1100
  type: "div",
1101
1101
  className: "min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100",
1102
- body: {
1102
+ children: {
1103
1103
  type: "card",
1104
1104
  className: "w-full max-w-md shadow-lg",
1105
1105
  title: "Welcome to Object UI",
1106
1106
  description: "Start building your application with JSON schemas",
1107
- body: {
1107
+ children: {
1108
1108
  type: "div",
1109
1109
  className: "p-6 space-y-4",
1110
- body: [
1110
+ children: [
1111
1111
  {
1112
1112
  type: "text",
1113
1113
  content: "This is a simple example. Edit app.json to customize your application.",
@@ -1125,19 +1125,19 @@ var templates = {
1125
1125
  form: {
1126
1126
  type: "div",
1127
1127
  className: "min-h-screen flex items-center justify-center bg-gradient-to-br from-purple-50 to-pink-100 p-4",
1128
- body: {
1128
+ children: {
1129
1129
  type: "card",
1130
1130
  className: "w-full max-w-2xl shadow-xl",
1131
1131
  title: "Contact Form",
1132
1132
  description: "Fill out the form below to get in touch",
1133
- body: {
1133
+ children: {
1134
1134
  type: "div",
1135
1135
  className: "p-6 space-y-6",
1136
- body: [
1136
+ children: [
1137
1137
  {
1138
1138
  type: "div",
1139
1139
  className: "grid grid-cols-2 gap-4",
1140
- body: [
1140
+ children: [
1141
1141
  {
1142
1142
  type: "input",
1143
1143
  label: "First Name",
@@ -1174,7 +1174,7 @@ var templates = {
1174
1174
  {
1175
1175
  type: "div",
1176
1176
  className: "flex gap-3",
1177
- body: [
1177
+ children: [
1178
1178
  {
1179
1179
  type: "button",
1180
1180
  label: "Submit",
@@ -1195,21 +1195,21 @@ var templates = {
1195
1195
  dashboard: {
1196
1196
  type: "div",
1197
1197
  className: "min-h-screen bg-muted/10",
1198
- body: [
1198
+ children: [
1199
1199
  {
1200
1200
  type: "div",
1201
1201
  className: "border-b bg-background",
1202
- body: {
1202
+ children: {
1203
1203
  type: "div",
1204
1204
  className: "container mx-auto px-6 py-4",
1205
- body: {
1205
+ children: {
1206
1206
  type: "div",
1207
1207
  className: "flex items-center justify-between",
1208
- body: [
1208
+ children: [
1209
1209
  {
1210
1210
  type: "div",
1211
1211
  className: "text-2xl font-bold",
1212
- body: { type: "text", content: "Dashboard" }
1212
+ children: { type: "text", content: "Dashboard" }
1213
1213
  },
1214
1214
  {
1215
1215
  type: "button",
@@ -1223,37 +1223,37 @@ var templates = {
1223
1223
  {
1224
1224
  type: "div",
1225
1225
  className: "container mx-auto p-6 space-y-6",
1226
- body: [
1226
+ children: [
1227
1227
  {
1228
1228
  type: "div",
1229
1229
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
1230
- body: [
1230
+ children: [
1231
1231
  {
1232
1232
  type: "card",
1233
1233
  className: "shadow-sm",
1234
- body: [
1234
+ children: [
1235
1235
  {
1236
1236
  type: "div",
1237
1237
  className: "p-6 pb-2",
1238
- body: {
1238
+ children: {
1239
1239
  type: "div",
1240
1240
  className: "text-sm font-medium text-muted-foreground",
1241
- body: { type: "text", content: "Total Revenue" }
1241
+ children: { type: "text", content: "Total Revenue" }
1242
1242
  }
1243
1243
  },
1244
1244
  {
1245
1245
  type: "div",
1246
1246
  className: "p-6 pt-0",
1247
- body: [
1247
+ children: [
1248
1248
  {
1249
1249
  type: "div",
1250
1250
  className: "text-2xl font-bold",
1251
- body: { type: "text", content: "$45,231.89" }
1251
+ children: { type: "text", content: "$45,231.89" }
1252
1252
  },
1253
1253
  {
1254
1254
  type: "div",
1255
1255
  className: "text-xs text-muted-foreground mt-1",
1256
- body: { type: "text", content: "+20.1% from last month" }
1256
+ children: { type: "text", content: "+20.1% from last month" }
1257
1257
  }
1258
1258
  ]
1259
1259
  }
@@ -1262,29 +1262,29 @@ var templates = {
1262
1262
  {
1263
1263
  type: "card",
1264
1264
  className: "shadow-sm",
1265
- body: [
1265
+ children: [
1266
1266
  {
1267
1267
  type: "div",
1268
1268
  className: "p-6 pb-2",
1269
- body: {
1269
+ children: {
1270
1270
  type: "div",
1271
1271
  className: "text-sm font-medium text-muted-foreground",
1272
- body: { type: "text", content: "Active Users" }
1272
+ children: { type: "text", content: "Active Users" }
1273
1273
  }
1274
1274
  },
1275
1275
  {
1276
1276
  type: "div",
1277
1277
  className: "p-6 pt-0",
1278
- body: [
1278
+ children: [
1279
1279
  {
1280
1280
  type: "div",
1281
1281
  className: "text-2xl font-bold",
1282
- body: { type: "text", content: "+2,350" }
1282
+ children: { type: "text", content: "+2,350" }
1283
1283
  },
1284
1284
  {
1285
1285
  type: "div",
1286
1286
  className: "text-xs text-muted-foreground mt-1",
1287
- body: { type: "text", content: "+180.1% from last month" }
1287
+ children: { type: "text", content: "+180.1% from last month" }
1288
1288
  }
1289
1289
  ]
1290
1290
  }
@@ -1293,29 +1293,29 @@ var templates = {
1293
1293
  {
1294
1294
  type: "card",
1295
1295
  className: "shadow-sm",
1296
- body: [
1296
+ children: [
1297
1297
  {
1298
1298
  type: "div",
1299
1299
  className: "p-6 pb-2",
1300
- body: {
1300
+ children: {
1301
1301
  type: "div",
1302
1302
  className: "text-sm font-medium text-muted-foreground",
1303
- body: { type: "text", content: "Sales" }
1303
+ children: { type: "text", content: "Sales" }
1304
1304
  }
1305
1305
  },
1306
1306
  {
1307
1307
  type: "div",
1308
1308
  className: "p-6 pt-0",
1309
- body: [
1309
+ children: [
1310
1310
  {
1311
1311
  type: "div",
1312
1312
  className: "text-2xl font-bold",
1313
- body: { type: "text", content: "+12,234" }
1313
+ children: { type: "text", content: "+12,234" }
1314
1314
  },
1315
1315
  {
1316
1316
  type: "div",
1317
1317
  className: "text-xs text-muted-foreground mt-1",
1318
- body: { type: "text", content: "+19% from last month" }
1318
+ children: { type: "text", content: "+19% from last month" }
1319
1319
  }
1320
1320
  ]
1321
1321
  }
@@ -1324,29 +1324,29 @@ var templates = {
1324
1324
  {
1325
1325
  type: "card",
1326
1326
  className: "shadow-sm",
1327
- body: [
1327
+ children: [
1328
1328
  {
1329
1329
  type: "div",
1330
1330
  className: "p-6 pb-2",
1331
- body: {
1331
+ children: {
1332
1332
  type: "div",
1333
1333
  className: "text-sm font-medium text-muted-foreground",
1334
- body: { type: "text", content: "Active Now" }
1334
+ children: { type: "text", content: "Active Now" }
1335
1335
  }
1336
1336
  },
1337
1337
  {
1338
1338
  type: "div",
1339
1339
  className: "p-6 pt-0",
1340
- body: [
1340
+ children: [
1341
1341
  {
1342
1342
  type: "div",
1343
1343
  className: "text-2xl font-bold",
1344
- body: { type: "text", content: "+573" }
1344
+ children: { type: "text", content: "+573" }
1345
1345
  },
1346
1346
  {
1347
1347
  type: "div",
1348
1348
  className: "text-xs text-muted-foreground mt-1",
1349
- body: { type: "text", content: "+201 since last hour" }
1349
+ children: { type: "text", content: "+201 since last hour" }
1350
1350
  }
1351
1351
  ]
1352
1352
  }
@@ -1359,27 +1359,27 @@ var templates = {
1359
1359
  className: "shadow-sm",
1360
1360
  title: "Recent Activity",
1361
1361
  description: "Your latest updates and notifications",
1362
- body: {
1362
+ children: {
1363
1363
  type: "div",
1364
1364
  className: "p-6 pt-0 space-y-4",
1365
- body: [
1365
+ children: [
1366
1366
  {
1367
1367
  type: "div",
1368
1368
  className: "flex items-center gap-4 border-b pb-4",
1369
- body: [
1369
+ children: [
1370
1370
  {
1371
1371
  type: "div",
1372
1372
  className: "flex-1",
1373
- body: [
1373
+ children: [
1374
1374
  {
1375
1375
  type: "div",
1376
1376
  className: "font-medium",
1377
- body: { type: "text", content: "New user registration" }
1377
+ children: { type: "text", content: "New user registration" }
1378
1378
  },
1379
1379
  {
1380
1380
  type: "div",
1381
1381
  className: "text-sm text-muted-foreground",
1382
- body: { type: "text", content: "2 minutes ago" }
1382
+ children: { type: "text", content: "2 minutes ago" }
1383
1383
  }
1384
1384
  ]
1385
1385
  }
@@ -1388,20 +1388,20 @@ var templates = {
1388
1388
  {
1389
1389
  type: "div",
1390
1390
  className: "flex items-center gap-4 border-b pb-4",
1391
- body: [
1391
+ children: [
1392
1392
  {
1393
1393
  type: "div",
1394
1394
  className: "flex-1",
1395
- body: [
1395
+ children: [
1396
1396
  {
1397
1397
  type: "div",
1398
1398
  className: "font-medium",
1399
- body: { type: "text", content: "Payment received" }
1399
+ children: { type: "text", content: "Payment received" }
1400
1400
  },
1401
1401
  {
1402
1402
  type: "div",
1403
1403
  className: "text-sm text-muted-foreground",
1404
- body: { type: "text", content: "15 minutes ago" }
1404
+ children: { type: "text", content: "15 minutes ago" }
1405
1405
  }
1406
1406
  ]
1407
1407
  }
@@ -1410,20 +1410,20 @@ var templates = {
1410
1410
  {
1411
1411
  type: "div",
1412
1412
  className: "flex items-center gap-4",
1413
- body: [
1413
+ children: [
1414
1414
  {
1415
1415
  type: "div",
1416
1416
  className: "flex-1",
1417
- body: [
1417
+ children: [
1418
1418
  {
1419
1419
  type: "div",
1420
1420
  className: "font-medium",
1421
- body: { type: "text", content: "New order placed" }
1421
+ children: { type: "text", content: "New order placed" }
1422
1422
  },
1423
1423
  {
1424
1424
  type: "div",
1425
1425
  className: "text-sm text-muted-foreground",
1426
- body: { type: "text", content: "1 hour ago" }
1426
+ children: { type: "text", content: "1 hour ago" }
1427
1427
  }
1428
1428
  ]
1429
1429
  }
@@ -1613,15 +1613,14 @@ async function init(name, options) {
1613
1613
  throw new Error(`Directory "${name}" already exists. Please choose a different name.`);
1614
1614
  }
1615
1615
  const targetDir = name === "." ? cwd : projectDir;
1616
+ const files = buildInitFiles(name, options.template);
1616
1617
  if (name !== ".") {
1617
1618
  mkdirSync3(projectDir, { recursive: true });
1618
1619
  }
1619
1620
  console.log(chalk4.blue("\u{1F3A8} Creating Object UI application..."));
1620
1621
  console.log(chalk4.dim(` Template: ${options.template}`));
1621
1622
  console.log();
1622
- for (const [relativePath, contents] of Object.entries(
1623
- buildInitFiles(name, options.template)
1624
- )) {
1623
+ for (const [relativePath, contents] of Object.entries(files)) {
1625
1624
  const target = join6(targetDir, relativePath);
1626
1625
  mkdirSync3(dirname5(target), { recursive: true });
1627
1626
  writeFileSync2(target, contents);
@@ -1652,4 +1651,4 @@ export {
1652
1651
  serve,
1653
1652
  init
1654
1653
  };
1655
- //# sourceMappingURL=chunk-AP2INOE7.js.map
1654
+ //# sourceMappingURL=chunk-VMMIGYU3.js.map