Skip to content

Commit 7eac7da

Browse files
committed
feat: 重构元数据 API,支持按类型列出项目并获取单个项目
1 parent 1425205 commit 7eac7da

File tree

4 files changed

+95
-59
lines changed

4 files changed

+95
-59
lines changed

examples/server/src/index.ts

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,59 @@ console.log('--- Plugins Loaded ---');
2121
// 3. Define Unified Routes
2222

2323
/**
24-
* Metadata API: Get All Objects
24+
* Unified Metadata API: List Items by Type
25+
* GET /api/v1/meta/objects
26+
* GET /api/v1/meta/apps
2527
*/
26-
app.get('/api/v1/meta/objects', (c) => {
27-
const objects = SchemaRegistry.getAll().map(obj => ({
28-
name: obj.name,
29-
label: obj.label,
30-
icon: obj.icon,
31-
path: `/api/v1/data/${obj.name}`
28+
app.get('/api/v1/meta/:type', (c) => {
29+
const typePlural = c.req.param('type');
30+
31+
// Simple singularization mapping (can be enhanced)
32+
const typeMap: Record<string, string> = {
33+
'objects': 'object',
34+
'apps': 'app',
35+
'flows': 'flow',
36+
'reports': 'report'
37+
};
38+
const type = typeMap[typePlural] || typePlural;
39+
40+
const items = SchemaRegistry.listItems(type);
41+
42+
// Optional: Summary transformation based on type
43+
const summaries = items.map((item: any) => ({
44+
name: item.name,
45+
label: item.label,
46+
icon: item.icon,
47+
description: item.description,
48+
// Add dynamic links
49+
...(type === 'object' ? { path: `/api/v1/data/${item.name}` } : {}),
50+
self: `/api/v1/meta/${typePlural}/${item.name}`
3251
}));
33-
return c.json({ data: objects });
34-
});
3552

36-
/**
37-
* Metadata API: Get Single Object
38-
*/
39-
app.get('/api/v1/meta/objects/:name', (c) => {
40-
const name = c.req.param('name');
41-
const schema = SchemaRegistry.get(name);
42-
if (!schema) return c.json({ error: 'Not found' }, 404);
43-
return c.json(schema);
53+
return c.json({ data: summaries });
4454
});
4555

4656
/**
47-
* Metadata API: Get All Apps
57+
* Unified Metadata API: Get Single Item
58+
* GET /api/v1/meta/objects/account
59+
* GET /api/v1/meta/apps/crm
4860
*/
49-
app.get('/api/v1/meta/apps', (c) => {
50-
const apps = SchemaRegistry.getAllApps().map(app => ({
51-
name: app.name,
52-
label: app.label,
53-
icon: app.icon,
54-
description: app.description,
55-
path: `/api/v1/meta/apps/${app.name}`
56-
}));
57-
return c.json({ data: apps });
58-
});
59-
60-
/**
61-
* Metadata API: Get Single App
62-
*/
63-
app.get('/api/v1/meta/apps/:name', (c) => {
61+
app.get('/api/v1/meta/:type/:name', (c) => {
62+
const typePlural = c.req.param('type');
6463
const name = c.req.param('name');
65-
const app = SchemaRegistry.getApp(name);
66-
if (!app) return c.json({ error: 'Not found' }, 404);
67-
return c.json(app);
64+
65+
const typeMap: Record<string, string> = {
66+
'objects': 'object',
67+
'apps': 'app',
68+
'flows': 'flow',
69+
'reports': 'report'
70+
};
71+
const type = typeMap[typePlural] || typePlural;
72+
73+
const item = SchemaRegistry.getItem(type, name);
74+
if (!item) return c.json({ error: `Metadata not found: ${type}/${name}` }, 404);
75+
76+
return c.json(item);
6877
});
6978

7079
/**
@@ -144,7 +153,7 @@ app.delete('/api/v1/data/:object/:id', async (c) => {
144153
});
145154

146155
// 4. Start Server
147-
const port = 3003;
156+
const port = 3004;
148157
console.log(`Server is running on http://localhost:${port}`);
149158

150159
serve({

examples/server/src/kernel/engine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class DataEngine {
6565
}
6666

6767
private ensureSchema(name: string): ServiceObject {
68-
const schema = SchemaRegistry.get(name);
68+
const schema = SchemaRegistry.getObject(name);
6969
if (!schema) throw new Error(`Unknown object: ${name}`);
7070
return schema;
7171
}

examples/server/src/kernel/registry.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,73 @@ import { ServiceObject, App } from '@objectstack/spec';
22

33
/**
44
* Global Schema Registry
5+
* Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)
56
*/
67
export class SchemaRegistry {
7-
private static objects = new Map<string, ServiceObject>();
8-
private static apps = new Map<string, App>();
8+
// Nested Map: Type -> Name -> MetadataItem
9+
private static metadata = new Map<string, Map<string, any>>();
910

1011
/**
11-
* Register a new object schema
12+
* Universal Register Method
1213
*/
13-
static register(schema: ServiceObject) {
14-
if (this.objects.has(schema.name)) {
15-
console.warn(`[Registry] Overwriting object: ${schema.name}`);
14+
static registerItem<T extends { name: string }>(type: string, item: T) {
15+
if (!this.metadata.has(type)) {
16+
this.metadata.set(type, new Map());
1617
}
17-
this.objects.set(schema.name, schema);
18-
console.log(`[Registry] Registered object: ${schema.name}`);
18+
const collection = this.metadata.get(type)!;
19+
20+
if (collection.has(item.name)) {
21+
console.warn(`[Registry] Overwriting ${type}: ${item.name}`);
22+
}
23+
collection.set(item.name, item);
24+
console.log(`[Registry] Registered ${type}: ${item.name}`);
25+
}
26+
27+
/**
28+
* Universal Get Method
29+
*/
30+
static getItem<T>(type: string, name: string): T | undefined {
31+
return this.metadata.get(type)?.get(name) as T;
32+
}
33+
34+
/**
35+
* Universal List Method
36+
*/
37+
static listItems<T>(type: string): T[] {
38+
return Array.from(this.metadata.get(type)?.values() || []) as T[];
39+
}
40+
41+
// ==========================================
42+
// Typed Helper Methods (Shortcuts)
43+
// ==========================================
44+
45+
/**
46+
* Object Helpers
47+
*/
48+
static registerObject(schema: ServiceObject) {
49+
this.registerItem('object', schema);
1950
}
2051

21-
static get(name: string): ServiceObject | undefined {
22-
return this.objects.get(name);
52+
static getObject(name: string): ServiceObject | undefined {
53+
return this.getItem<ServiceObject>('object', name);
2354
}
2455

25-
static getAll(): ServiceObject[] {
26-
return Array.from(this.objects.values());
56+
static getAllObjects(): ServiceObject[] {
57+
return this.listItems<ServiceObject>('object');
2758
}
2859

2960
/**
30-
* Register a new app schema
61+
* App Helpers
3162
*/
3263
static registerApp(app: App) {
33-
if (this.apps.has(app.name)) {
34-
console.warn(`[Registry] Overwriting app: ${app.name}`);
35-
}
36-
this.apps.set(app.name, app);
37-
console.log(`[Registry] Registered app: ${app.name}`);
64+
this.registerItem('app', app);
3865
}
3966

4067
static getApp(name: string): App | undefined {
41-
return this.apps.get(name);
68+
return this.getItem<App>('app', name);
4269
}
4370

4471
static getAllApps(): App[] {
45-
return Array.from(this.apps.values());
72+
return this.listItems<App>('app');
4673
}
4774
}

examples/server/src/loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function loadPlugins() {
2323
// 1. Register Objects
2424
if (app.objects) {
2525
app.objects.forEach((obj: any) => {
26-
SchemaRegistry.register(obj);
26+
SchemaRegistry.registerObject(obj);
2727
});
2828
}
2929

0 commit comments

Comments
 (0)