Skip to content

Commit 2f67510

Browse files
Copilothotlong
andcommitted
Changes before error encountered
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 009dbae commit 2f67510

4 files changed

Lines changed: 76 additions & 13 deletions

File tree

docs/CLI_GUIDE.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,15 +171,23 @@ Create a `pages/` directory with your schema files:
171171
my-app/
172172
├── pages/
173173
│ ├── index.schema.json → /
174-
│ ├── about.schema.json → /about
174+
│ ├── about.page.json → /about
175175
│ ├── blog/
176-
│ │ ├── index.schema.json → /blog
177-
│ │ └── [id].schema.json → /blog/:id
176+
│ │ ├── index.page.yml → /blog
177+
│ │ └── [id].schema.yaml → /blog/:id
178178
│ └── users/
179-
│ └── [userId].schema.json → /users/:userId
179+
│ └── [userId].page.json → /users/:userId
180180
└── app.schema.json (optional, reserved for future layout support)
181181
```
182182

183+
**Supported File Extensions:**
184+
- `.schema.json` - JSON schema file
185+
- `.page.json` - Alternative JSON format
186+
- `.schema.yml` / `.schema.yaml` - YAML schema file
187+
- `.page.yml` / `.page.yaml` - Alternative YAML format
188+
189+
All formats are equivalent - use whichever you prefer. YAML files are parsed automatically.
190+
183191
#### Example Page Schemas
184192

185193
**pages/index.schema.json:**
@@ -198,6 +206,18 @@ my-app/
198206
}
199207
```
200208

209+
**pages/about.page.yml (YAML format):**
210+
```yaml
211+
type: div
212+
className: p-8
213+
body:
214+
type: card
215+
title: About Page
216+
body:
217+
type: text
218+
content: Learn more about us!
219+
```
220+
201221
**pages/about.schema.json:**
202222
```json
203223
{

packages/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@
3636
"vite": "^5.0.0",
3737
"@vitejs/plugin-react": "^4.2.1",
3838
"express": "^4.21.2",
39+
"js-yaml": "^4.1.0",
3940
"@object-ui/react": "workspace:*",
4041
"@object-ui/components": "workspace:*"
4142
},
4243
"devDependencies": {
4344
"@types/express": "^4.17.21",
4445
"@types/node": "^24.10.8",
46+
"@types/js-yaml": "^4.0.9",
4547
"tsup": "^8.0.0",
4648
"typescript": "^5.0.0"
4749
}

packages/cli/src/commands/serve.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react';
33
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'fs';
44
import { join, resolve, relative, basename, dirname } from 'path';
55
import chalk from 'chalk';
6+
import * as yaml from 'js-yaml';
67

78
interface ServeOptions {
89
port: string;
@@ -55,10 +56,9 @@ export async function serve(schemaPath: string, options: ServeOptions) {
5556

5657
// Read and validate schema
5758
try {
58-
const schemaContent = readFileSync(fullSchemaPath, 'utf-8');
59-
schema = JSON.parse(schemaContent);
59+
schema = parseSchemaFile(fullSchemaPath);
6060
} catch (error) {
61-
throw new Error(`Invalid JSON in schema file: ${error instanceof Error ? error.message : error}`);
61+
throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);
6262
}
6363
}
6464

@@ -362,6 +362,37 @@ export default {
362362
writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));
363363
}
364364

365+
// Helper function to check if a file is a supported schema file
366+
function isSupportedSchemaFile(filename: string): boolean {
367+
return filename.endsWith('.schema.json') ||
368+
filename.endsWith('.page.json') ||
369+
filename.endsWith('.schema.yml') ||
370+
filename.endsWith('.schema.yaml') ||
371+
filename.endsWith('.page.yml') ||
372+
filename.endsWith('.page.yaml');
373+
}
374+
375+
// Helper function to extract the base filename without extension
376+
function getBaseFileName(filename: string): string {
377+
// Remove supported extensions
378+
return filename
379+
.replace(/\.schema\.(json|yml|yaml)$/, '')
380+
.replace(/\.page\.(json|yml|yaml)$/, '');
381+
}
382+
383+
// Helper function to parse schema file (JSON or YAML)
384+
function parseSchemaFile(filePath: string): any {
385+
const content = readFileSync(filePath, 'utf-8');
386+
387+
if (filePath.endsWith('.json')) {
388+
return JSON.parse(content);
389+
} else if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) {
390+
return yaml.load(content);
391+
}
392+
393+
throw new Error(`Unsupported file format: ${filePath}`);
394+
}
395+
365396
function scanPagesDirectory(pagesDir: string): RouteInfo[] {
366397
const routes: RouteInfo[] = [];
367398

@@ -376,15 +407,15 @@ function scanPagesDirectory(pagesDir: string): RouteInfo[] {
376407
// Recursively scan subdirectories
377408
const newPrefix = routePrefix + '/' + entry;
378409
scanDir(fullPath, newPrefix);
379-
} else if (entry.endsWith('.schema.json')) {
410+
} else if (isSupportedSchemaFile(entry)) {
380411
// Process schema file
381-
const fileName = basename(entry, '.schema.json');
412+
const fileName = getBaseFileName(entry);
382413
let routePath: string;
383414
let isDynamic = false;
384415
let paramName: string | undefined;
385416

386417
if (fileName === 'index') {
387-
// index.schema.json maps to the directory path
418+
// index.schema.json or index.page.json maps to the directory path
388419
routePath = routePrefix || '/';
389420
} else if (fileName.startsWith('[') && fileName.endsWith(']')) {
390421
// Dynamic route: [id].schema.json -> /:id
@@ -398,8 +429,7 @@ function scanPagesDirectory(pagesDir: string): RouteInfo[] {
398429

399430
// Read and parse schema
400431
try {
401-
const schemaContent = readFileSync(fullPath, 'utf-8');
402-
const schema = JSON.parse(schemaContent);
432+
const schema = parseSchemaFile(fullPath);
403433

404434
routes.push({
405435
path: routePath,
@@ -409,7 +439,7 @@ function scanPagesDirectory(pagesDir: string): RouteInfo[] {
409439
paramName,
410440
});
411441
} catch (error) {
412-
console.warn(chalk.yellow(`⚠ Warning: Failed to parse ${fullPath}`));
442+
console.warn(chalk.yellow(`⚠ Warning: Failed to parse ${fullPath}: ${error instanceof Error ? error.message : error}`));
413443
}
414444
}
415445
}

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)