Skip to content

Commit cc9738d

Browse files
committed
添加 @objectstack/server 包及其相关配置,包含 ObjectStackServer 实现和数据引擎;更新示例以支持新功能和插件;重构数据引擎以简化服务器配置
1 parent 18428ba commit cc9738d

File tree

8 files changed

+501
-213
lines changed

8 files changed

+501
-213
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { ServiceObject } from '@objectstack/spec';
2+
import { SchemaRegistry } from './registry';
3+
import { ObjectQL } from './engine';
4+
5+
/**
6+
* Server Data Engine Wrapper
7+
*
8+
* This class is now a thin wrapper that initializes the ObjectQL Engine
9+
* with the appropriate Server-Side configuration (Registry, Drivers).
10+
*
11+
* The core logic has been moved to @objectstack/objectql.
12+
*/
13+
export class DataEngine {
14+
public ql: ObjectQL;
15+
private plugins: any[];
16+
17+
constructor(plugins: any[] = []) {
18+
// 1. Initialize Engine with Host Context (Simulated OS services)
19+
this.ql = new ObjectQL({
20+
env: process.env.NODE_ENV || 'development'
21+
});
22+
this.plugins = plugins;
23+
}
24+
25+
async start() {
26+
console.log('[DataEngine] Starting...');
27+
28+
// 0. Register Provided Plugins
29+
this.plugins.forEach(p => {
30+
console.log(`[DataEngine] Loading Plugin: ${p.name}`);
31+
SchemaRegistry.registerPlugin(p);
32+
});
33+
34+
// 1. Load Drivers (Default to Memory if none provided in plugins)
35+
// TODO: Detect driver from plugins. For now, we still hard load memory driver if needed?
36+
// In strict mode, user should pass driver in plugins array (DriverManifest).
37+
// check if driver is registered
38+
39+
// For Backwards Compat / Easy Dev, try dynamic import of memory driver if installed
40+
try {
41+
// @ts-ignore
42+
const { InMemoryDriver } = await import('@objectstack/plugin-driver-memory');
43+
const driver = new InMemoryDriver();
44+
this.ql.registerDriver(driver);
45+
} catch (e) {
46+
// Ignore if not present
47+
}
48+
49+
// 2. Initialize Engine
50+
await this.ql.init();
51+
52+
53+
// 3. Seed Data
54+
await this.seed();
55+
}
56+
57+
async seed() {
58+
// If no driver registered yet, this might fail or wait.
59+
// In real world, we wait for 'ready' event.
60+
try {
61+
// Mock System Table
62+
try {
63+
// We don't have SystemStatus defined in schema usually, skipping for general engine
64+
// await this.ql.insert('SystemStatus', { status: 'OK', uptime: 0 });
65+
} catch {}
66+
67+
// Iterate over all registered plugins/apps and check for 'data' property in manifest
68+
69+
const plugins = SchemaRegistry.getRegisteredTypes(); // This returns types like 'plugin', 'app'
70+
71+
// This is a bit hacky because we don't have a direct "getAllManifests" API exposed easily
72+
// We will iterate known apps for now, or improve Registry API later.
73+
// Actually, SchemaRegistry.listItems('app') returns the manifests!
74+
75+
const apps = [...SchemaRegistry.listItems('app'), ...SchemaRegistry.listItems('plugin')];
76+
77+
for (const appItem of apps) {
78+
const app = appItem as any; // Cast to access data prop safely
79+
if (app.data && Array.isArray(app.data)) {
80+
console.log(`[DataEngine] Seeding data for ${app.name || app.id}...`);
81+
for (const seed of app.data) {
82+
try {
83+
// Check if data exists
84+
const existing = await this.ql.find(seed.object, { top: 1 });
85+
if (existing.length === 0) {
86+
console.log(`[DataEngine] Inserting ${seed.records.length} records into ${seed.object}`);
87+
for (const record of seed.records) {
88+
await this.ql.insert(seed.object, record);
89+
}
90+
}
91+
} catch (e) {
92+
console.warn(`[DataEngine] Failed to seed ${seed.object}`, e);
93+
}
94+
}
95+
}
96+
}
97+
98+
} catch(e) {
99+
console.warn('Seed failed (driver might not be ready):', e);
100+
}
101+
}
102+
103+
// Forward methods to ObjectQL
104+
async find(objectName: string, query: any) {
105+
this.ensureSchema(objectName);
106+
const results = await this.ql.find(objectName, { top: 100 });
107+
return { value: results, count: results.length };
108+
}
109+
110+
async get(objectName: string, id: string) {
111+
this.ensureSchema(objectName);
112+
// Find One
113+
const results = await this.ql.find(objectName, { top: 1 }); // Mock implementation
114+
return results[0];
115+
}
116+
117+
async create(objectName: string, data: any) {
118+
this.ensureSchema(objectName);
119+
return this.ql.insert(objectName, data);
120+
}
121+
122+
async update(objectName: string, id: string, data: any) {
123+
this.ensureSchema(objectName);
124+
return this.ql.update(objectName, id, data);
125+
}
126+
127+
async delete(objectName: string, id: string) {
128+
this.ensureSchema(objectName);
129+
return this.ql.delete(objectName, id);
130+
}
131+
132+
// [New Methods for ObjectUI]
133+
getMetadata(objectName: string) {
134+
return this.ensureSchema(objectName);
135+
}
136+
137+
getView(objectName: string, viewType: 'list' | 'form' = 'list') {
138+
const schema = this.ensureSchema(objectName);
139+
140+
// Auto-Scaffold Default View
141+
if (viewType === 'list') {
142+
return {
143+
type: 'datagrid',
144+
title: `${schema.label || objectName} List`,
145+
columns: Object.keys(schema.fields || {}).map(key => ({
146+
field: key,
147+
label: schema.fields?.[key]?.label || key,
148+
width: 150
149+
})),
150+
actions: ['create', 'edit', 'delete']
151+
};
152+
}
153+
return null;
154+
}
155+
156+
private ensureSchema(name: string): ServiceObject {
157+
const schema = SchemaRegistry.getObject(name);
158+
if (!schema) throw new Error(`Unknown object: ${name}`);
159+
return schema;
160+
}
161+
}

examples/objectql/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Export core engine
22
export { ObjectQL } from './engine';
33
export { SchemaRegistry } from './registry';
4+
export { DataEngine } from './data-engine';
5+
6+
47

58
// Re-export common types from spec for convenience
69
export type { DriverInterface, DriverOptions, QueryAST } from '@objectstack/spec';

examples/server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"build": "tsc"
88
},
99
"dependencies": {
10+
"@objectstack/server": "workspace:*",
1011
"@objectstack/spec": "workspace:*",
1112
"@objectstack/example-crm": "workspace:*",
1213
"@objectstack/example-todo": "workspace:*",

0 commit comments

Comments
 (0)