Skip to content

Commit 178494a

Browse files
Copilothotlong
andcommitted
refactor: migrate @object-ui/cli to @objectstack/plugin-ui with oclif commands
- Renamed package from @object-ui/cli to @objectstack/plugin-ui - Created 15 oclif Command classes under src/commands/ui/ - Added @oclif/core dependency and oclif plugin configuration in package.json - Updated tsup.config.ts with separate build configs for lib and oclif commands - Preserved backward-compatible Commander.js CLI entry (cli.ts) - Fixed pre-existing TS issues in dev.ts and start.ts surfaced by new build scope Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent d3a538e commit 178494a

21 files changed

Lines changed: 763 additions & 530 deletions

packages/cli/package.json

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "@object-ui/cli",
2+
"name": "@objectstack/plugin-ui",
33
"version": "3.0.3",
4-
"description": "CLI tool for Object UI - Build applications from JSON schemas",
4+
"description": "ObjectStack CLI plugin for Object UI — oclif-based UI toolchain commands (os ui dev, os ui build, etc.)",
55
"type": "module",
66
"homepage": "https://www.objectui.org",
77
"repository": {
@@ -28,21 +28,29 @@
2828
"scripts": {
2929
"build": "tsup",
3030
"dev": "tsup --watch",
31-
"lint": "eslint src"
31+
"lint": "eslint src",
32+
"test": "vitest run"
3233
},
3334
"keywords": [
35+
"objectstack",
3436
"object-ui",
37+
"oclif-plugin",
3538
"cli",
3639
"schema-driven",
3740
"ui-builder",
3841
"json"
3942
],
40-
"author": "ObjectQL Team",
43+
"author": "ObjectStack Team",
4144
"license": "MIT",
45+
"oclif": {
46+
"commands": "./dist/commands",
47+
"hooks": {}
48+
},
4249
"dependencies": {
4350
"@object-ui/components": "workspace:*",
4451
"@object-ui/react": "workspace:*",
4552
"@object-ui/types": "workspace:*",
53+
"@oclif/core": "^4.8.0",
4654
"@types/glob": "^9.0.0",
4755
"@vitejs/plugin-react": "^5.1.4",
4856
"chalk": "^5.6.2",
@@ -58,6 +66,7 @@
5866
"@types/js-yaml": "^4.0.9",
5967
"@types/node": "^25.2.3",
6068
"tsup": "^8.5.1",
61-
"typescript": "^5.9.3"
69+
"typescript": "^5.9.3",
70+
"vitest": "^4.0.18"
6271
}
6372
}

packages/cli/src/commands/dev.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ export async function dev(schemaPath: string, options: DevOptions) {
193193
// We might get the cjs entry, but for aliasing usually fine.
194194
// Better yet, if we can find the package root, but require.resolve gives file.
195195
// Let's just use what require.resolve gives.
196-
// @ts-expect-error - lucidePath is dynamically resolved
196+
// @ts-ignore - lucidePath is dynamically resolved
197197
viteConfig.resolve.alias['lucide-react'] = lucidePath;
198198
} catch (e) {
199199
console.warn('⚠️ Could not resolve lucide-react automatically:', e);

packages/cli/src/commands/start.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export async function start(options: StartOptions) {
6262
app.use(express.static(distPath));
6363

6464
// SPA fallback - serve index.html for all routes
65-
app.get('*', (req, res) => {
65+
app.get('*', (_req, res) => {
6666
res.sendFile(indexPath);
6767
});
6868

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command, Args } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { add } from '../add.js';
11+
12+
export default class Add extends Command {
13+
static override description = 'Add a new component renderer to your project';
14+
15+
static override args = {
16+
component: Args.string({
17+
description: 'Component name (e.g. Input, Grid)',
18+
required: true,
19+
}),
20+
};
21+
22+
async run(): Promise<void> {
23+
const { args } = await this.parse(Add);
24+
try {
25+
await add(args.component);
26+
} catch (error) {
27+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
28+
}
29+
}
30+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command, Flags } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { analyze } from '../analyze.js';
11+
12+
export default class Analyze extends Command {
13+
static override description = 'Analyze application performance';
14+
15+
static override flags = {
16+
'bundle-size': Flags.boolean({
17+
description: 'Analyze bundle size',
18+
default: false,
19+
}),
20+
'render-performance': Flags.boolean({
21+
description: 'Analyze render performance',
22+
default: false,
23+
}),
24+
};
25+
26+
async run(): Promise<void> {
27+
const { flags } = await this.parse(Analyze);
28+
try {
29+
await analyze({
30+
bundleSize: flags['bundle-size'],
31+
renderPerformance: flags['render-performance'],
32+
});
33+
} catch (error) {
34+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
35+
}
36+
}
37+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command, Args, Flags } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { buildApp } from '../build.js';
11+
12+
export default class Build extends Command {
13+
static override description = 'Build application for production';
14+
15+
static override args = {
16+
schema: Args.string({
17+
description: 'Path to JSON/YAML schema file',
18+
default: 'app.json',
19+
}),
20+
};
21+
22+
static override flags = {
23+
'out-dir': Flags.string({
24+
char: 'o',
25+
description: 'Output directory',
26+
default: 'dist',
27+
}),
28+
clean: Flags.boolean({
29+
description: 'Clean output directory before build',
30+
default: false,
31+
}),
32+
};
33+
34+
async run(): Promise<void> {
35+
const { args, flags } = await this.parse(Build);
36+
try {
37+
await buildApp(args.schema, {
38+
outDir: flags['out-dir'],
39+
clean: flags.clean,
40+
});
41+
} catch (error) {
42+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
43+
}
44+
}
45+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { check } from '../check.js';
11+
12+
export default class Check extends Command {
13+
static override description = 'Validate schema files';
14+
15+
async run(): Promise<void> {
16+
try {
17+
await check();
18+
} catch (error) {
19+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
20+
}
21+
}
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command, Args } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { createPlugin } from '../create-plugin.js';
11+
12+
export default class CreatePlugin extends Command {
13+
static override description = 'Create a new ObjectUI plugin';
14+
15+
static override args = {
16+
name: Args.string({
17+
description: 'Name of the plugin',
18+
required: true,
19+
}),
20+
};
21+
22+
async run(): Promise<void> {
23+
const { args } = await this.parse(CreatePlugin);
24+
try {
25+
await createPlugin(args.name);
26+
} catch (error) {
27+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
28+
}
29+
}
30+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command, Args, Flags } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { dev } from '../dev.js';
11+
12+
export default class Dev extends Command {
13+
static override description = 'Start development server (alias for serve)';
14+
15+
static override args = {
16+
schema: Args.string({
17+
description: 'Path to JSON/YAML schema file',
18+
default: 'app.json',
19+
}),
20+
};
21+
22+
static override flags = {
23+
port: Flags.string({
24+
char: 'p',
25+
description: 'Port to run the server on',
26+
default: '3000',
27+
}),
28+
host: Flags.string({
29+
char: 'H',
30+
description: 'Host to bind the server to',
31+
default: 'localhost',
32+
}),
33+
open: Flags.boolean({
34+
description: 'Open browser automatically',
35+
default: true,
36+
allowNo: true,
37+
}),
38+
};
39+
40+
async run(): Promise<void> {
41+
const { args, flags } = await this.parse(Dev);
42+
try {
43+
await dev(args.schema, {
44+
port: flags.port,
45+
host: flags.host,
46+
open: flags.open,
47+
});
48+
} catch (error) {
49+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
50+
}
51+
}
52+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* ObjectUI — oclif plugin command
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
import { Command } from '@oclif/core';
9+
import chalk from 'chalk';
10+
import { doctor } from '../doctor.js';
11+
12+
export default class Doctor extends Command {
13+
static override description = 'Diagnose and fix common issues';
14+
15+
async run(): Promise<void> {
16+
try {
17+
await doctor();
18+
} catch (error) {
19+
this.error(chalk.red(error instanceof Error ? error.message : String(error)));
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)