@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/CHANGELOG.md +2505 -0
- package/README.md +14 -24
- package/dist/{chunk-AP2INOE7.js → chunk-VMMIGYU3.js} +79 -80
- package/dist/chunk-VMMIGYU3.js.map +1 -0
- package/dist/cli.js +621 -507
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +7 -6
- package/dist/chunk-AP2INOE7.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @object-ui/cli
|
|
2
2
|
|
|
3
|
-
> Standalone CLI for **Object UI** — scaffold, develop, build
|
|
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
|
-
|
|
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.
|
|
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 {
|
|
539
|
+
import type { ReactNode } from 'react';
|
|
540
540
|
import { Link, useLocation } from 'react-router-dom';
|
|
541
|
-
import
|
|
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
|
-
//
|
|
586
|
-
//
|
|
587
|
-
//
|
|
588
|
-
//
|
|
589
|
-
//
|
|
590
|
-
//
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
-
|
|
598
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
622
|
+
<Sun className="mr-2 size-4" />
|
|
623
623
|
Light
|
|
624
624
|
</DropdownMenuItem>
|
|
625
625
|
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
|
626
|
-
<
|
|
626
|
+
<Moon className="mr-2 size-4" />
|
|
627
627
|
Dark
|
|
628
628
|
</DropdownMenuItem>
|
|
629
629
|
<DropdownMenuItem onClick={() => setTheme("system")}>
|
|
630
|
-
<
|
|
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
|
-
|
|
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
|
-
|
|
1107
|
+
children: {
|
|
1108
1108
|
type: "div",
|
|
1109
1109
|
className: "p-6 space-y-4",
|
|
1110
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1133
|
+
children: {
|
|
1134
1134
|
type: "div",
|
|
1135
1135
|
className: "p-6 space-y-6",
|
|
1136
|
-
|
|
1136
|
+
children: [
|
|
1137
1137
|
{
|
|
1138
1138
|
type: "div",
|
|
1139
1139
|
className: "grid grid-cols-2 gap-4",
|
|
1140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1198
|
+
children: [
|
|
1199
1199
|
{
|
|
1200
1200
|
type: "div",
|
|
1201
1201
|
className: "border-b bg-background",
|
|
1202
|
-
|
|
1202
|
+
children: {
|
|
1203
1203
|
type: "div",
|
|
1204
1204
|
className: "container mx-auto px-6 py-4",
|
|
1205
|
-
|
|
1205
|
+
children: {
|
|
1206
1206
|
type: "div",
|
|
1207
1207
|
className: "flex items-center justify-between",
|
|
1208
|
-
|
|
1208
|
+
children: [
|
|
1209
1209
|
{
|
|
1210
1210
|
type: "div",
|
|
1211
1211
|
className: "text-2xl font-bold",
|
|
1212
|
-
|
|
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
|
-
|
|
1226
|
+
children: [
|
|
1227
1227
|
{
|
|
1228
1228
|
type: "div",
|
|
1229
1229
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
1230
|
-
|
|
1230
|
+
children: [
|
|
1231
1231
|
{
|
|
1232
1232
|
type: "card",
|
|
1233
1233
|
className: "shadow-sm",
|
|
1234
|
-
|
|
1234
|
+
children: [
|
|
1235
1235
|
{
|
|
1236
1236
|
type: "div",
|
|
1237
1237
|
className: "p-6 pb-2",
|
|
1238
|
-
|
|
1238
|
+
children: {
|
|
1239
1239
|
type: "div",
|
|
1240
1240
|
className: "text-sm font-medium text-muted-foreground",
|
|
1241
|
-
|
|
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
|
-
|
|
1247
|
+
children: [
|
|
1248
1248
|
{
|
|
1249
1249
|
type: "div",
|
|
1250
1250
|
className: "text-2xl font-bold",
|
|
1251
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1265
|
+
children: [
|
|
1266
1266
|
{
|
|
1267
1267
|
type: "div",
|
|
1268
1268
|
className: "p-6 pb-2",
|
|
1269
|
-
|
|
1269
|
+
children: {
|
|
1270
1270
|
type: "div",
|
|
1271
1271
|
className: "text-sm font-medium text-muted-foreground",
|
|
1272
|
-
|
|
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
|
-
|
|
1278
|
+
children: [
|
|
1279
1279
|
{
|
|
1280
1280
|
type: "div",
|
|
1281
1281
|
className: "text-2xl font-bold",
|
|
1282
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1296
|
+
children: [
|
|
1297
1297
|
{
|
|
1298
1298
|
type: "div",
|
|
1299
1299
|
className: "p-6 pb-2",
|
|
1300
|
-
|
|
1300
|
+
children: {
|
|
1301
1301
|
type: "div",
|
|
1302
1302
|
className: "text-sm font-medium text-muted-foreground",
|
|
1303
|
-
|
|
1303
|
+
children: { type: "text", content: "Sales" }
|
|
1304
1304
|
}
|
|
1305
1305
|
},
|
|
1306
1306
|
{
|
|
1307
1307
|
type: "div",
|
|
1308
1308
|
className: "p-6 pt-0",
|
|
1309
|
-
|
|
1309
|
+
children: [
|
|
1310
1310
|
{
|
|
1311
1311
|
type: "div",
|
|
1312
1312
|
className: "text-2xl font-bold",
|
|
1313
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1327
|
+
children: [
|
|
1328
1328
|
{
|
|
1329
1329
|
type: "div",
|
|
1330
1330
|
className: "p-6 pb-2",
|
|
1331
|
-
|
|
1331
|
+
children: {
|
|
1332
1332
|
type: "div",
|
|
1333
1333
|
className: "text-sm font-medium text-muted-foreground",
|
|
1334
|
-
|
|
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
|
-
|
|
1340
|
+
children: [
|
|
1341
1341
|
{
|
|
1342
1342
|
type: "div",
|
|
1343
1343
|
className: "text-2xl font-bold",
|
|
1344
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1362
|
+
children: {
|
|
1363
1363
|
type: "div",
|
|
1364
1364
|
className: "p-6 pt-0 space-y-4",
|
|
1365
|
-
|
|
1365
|
+
children: [
|
|
1366
1366
|
{
|
|
1367
1367
|
type: "div",
|
|
1368
1368
|
className: "flex items-center gap-4 border-b pb-4",
|
|
1369
|
-
|
|
1369
|
+
children: [
|
|
1370
1370
|
{
|
|
1371
1371
|
type: "div",
|
|
1372
1372
|
className: "flex-1",
|
|
1373
|
-
|
|
1373
|
+
children: [
|
|
1374
1374
|
{
|
|
1375
1375
|
type: "div",
|
|
1376
1376
|
className: "font-medium",
|
|
1377
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1391
|
+
children: [
|
|
1392
1392
|
{
|
|
1393
1393
|
type: "div",
|
|
1394
1394
|
className: "flex-1",
|
|
1395
|
-
|
|
1395
|
+
children: [
|
|
1396
1396
|
{
|
|
1397
1397
|
type: "div",
|
|
1398
1398
|
className: "font-medium",
|
|
1399
|
-
|
|
1399
|
+
children: { type: "text", content: "Payment received" }
|
|
1400
1400
|
},
|
|
1401
1401
|
{
|
|
1402
1402
|
type: "div",
|
|
1403
1403
|
className: "text-sm text-muted-foreground",
|
|
1404
|
-
|
|
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
|
-
|
|
1413
|
+
children: [
|
|
1414
1414
|
{
|
|
1415
1415
|
type: "div",
|
|
1416
1416
|
className: "flex-1",
|
|
1417
|
-
|
|
1417
|
+
children: [
|
|
1418
1418
|
{
|
|
1419
1419
|
type: "div",
|
|
1420
1420
|
className: "font-medium",
|
|
1421
|
-
|
|
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
|
-
|
|
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-
|
|
1654
|
+
//# sourceMappingURL=chunk-VMMIGYU3.js.map
|