Skip to content

Commit d83f972

Browse files
committed
添加内存驱动插件及相关配置,导出驱动协议,更新 TypeScript 配置
1 parent 8c2305e commit d83f972

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ObjectStackManifest } from '@objectstack/spec';
2+
3+
const MemoryDriverPlugin: ObjectStackManifest = {
4+
id: 'com.objectstack.driver.memory',
5+
name: 'In-Memory Driver',
6+
version: '1.0.0',
7+
type: 'plugin', // Acts as a plugin that contributes a driver
8+
description: 'A reference specificiation implementation of the DriverInterface using in-memory arrays.',
9+
10+
configuration: {
11+
title: 'Memory Driver Settings',
12+
properties: {
13+
seedData: {
14+
type: 'boolean',
15+
default: false,
16+
description: 'Pre-populate the database with example data on startup'
17+
}
18+
}
19+
},
20+
21+
contributes: {
22+
// If there was a 'drivers' definition here, we would use it.
23+
// For now, we register via code (src/index.ts)
24+
}
25+
};
26+
27+
export default MemoryDriverPlugin;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "@objectstack/plugin-driver-memory",
3+
"version": "0.0.1",
4+
"description": "Example: In-Memory Database Driver for ObjectStack",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"scripts": {
8+
"build": "tsc",
9+
"dev": "tsc -w"
10+
},
11+
"dependencies": {
12+
"@objectstack/spec": "workspace:*"
13+
},
14+
"devDependencies": {
15+
"typescript": "^5.0.0"
16+
}
17+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { InMemoryDriver } from './memory-driver';
2+
3+
// Note: In a real environment, you would import these from @objectstack/spec
4+
// But distinct PluginDefinition interface might not be strictly defined in schema yet,
5+
// usually it mimics the Manifest structure + runtime hooks.
6+
7+
// For this example, we define a basic shape if not available, or use "any" to bypass strictness for the demo.
8+
// In plugin-bi it imported: import { PluginDefinition, PluginContextData } from '@objectstack/spec';
9+
10+
// Let's rely on the environment being set up like plugin-bi.
11+
// If types are missing, this is just an example file.
12+
13+
export default {
14+
id: 'com.objectstack.driver.memory',
15+
version: '1.0.0',
16+
17+
onEnable: async (context: any) => {
18+
const { logger } = context;
19+
logger.info('[Memory Driver] Initializing...');
20+
21+
// Simulate driver registration
22+
// This assumes the runtime exposes a 'drivers' registry
23+
if (context.drivers) {
24+
const driver = new InMemoryDriver();
25+
context.drivers.register(driver);
26+
logger.info(`[Memory Driver] Registered driver: ${driver.name}`);
27+
} else {
28+
logger.warn('[Memory Driver] No driver registry found in context.');
29+
}
30+
}
31+
};
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import {
2+
DriverInterface,
3+
DriverOptions,
4+
QueryAST // Ensure this is exported from spec
5+
} from '@objectstack/spec';
6+
7+
/**
8+
* Example: In-Memory Driver
9+
*
10+
* A minimal reference implementation of the ObjectStack Driver Protocol.
11+
* This driver stores data in a simple JavaScript object (Heap).
12+
*/
13+
export class InMemoryDriver implements DriverInterface {
14+
name = 'in-memory-driver';
15+
version = '0.0.1';
16+
17+
supports = {
18+
transactions: false,
19+
joins: false,
20+
fullTextSearch: false,
21+
jsonFields: true,
22+
arrayFields: true,
23+
};
24+
25+
/**
26+
* The "Database": A map of TableName -> Array of Records
27+
*/
28+
private db: Record<string, any[]> = {};
29+
30+
// ===================================
31+
// Lifecycle
32+
// ===================================
33+
34+
async connect() {
35+
console.log('🔌 [InMemory] Database Connected (Virtual)');
36+
}
37+
38+
async disconnect() {
39+
this.db = {};
40+
console.log('🔌 [InMemory] Database Disconnected & Cleared');
41+
}
42+
43+
async checkHealth() {
44+
return true;
45+
}
46+
47+
// ===================================
48+
// Execution
49+
// ===================================
50+
51+
async execute(command: any, params?: any[]) {
52+
console.log('⚠️ [InMemory] Raw execution not supported, received:', command);
53+
return null;
54+
}
55+
56+
// ===================================
57+
// CRUD
58+
// ===================================
59+
60+
async find(object: string, query: QueryAST, options?: DriverOptions) {
61+
const table = this.getTable(object);
62+
63+
// 💡 Naive Implementation
64+
let results = [...table];
65+
66+
// Simple limiting for demonstration
67+
if (query.top) {
68+
results = results.slice(0, query.top);
69+
}
70+
71+
return results;
72+
}
73+
74+
async findOne(object: string, query: QueryAST, options?: DriverOptions) {
75+
const results = await this.find(object, { ...query, top: 1 }, options);
76+
return results[0] || null;
77+
}
78+
79+
async create(object: string, data: Record<string, any>, options?: DriverOptions) {
80+
const table = this.getTable(object);
81+
82+
const newRecord = {
83+
id: this.generateId(),
84+
...data,
85+
created_at: new Date(),
86+
updated_at: new Date(),
87+
};
88+
89+
table.push(newRecord);
90+
return newRecord;
91+
}
92+
93+
async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions) {
94+
const table = this.getTable(object);
95+
const index = table.findIndex(r => r.id == id);
96+
97+
if (index === -1) {
98+
throw new Error(`Record with ID ${id} not found in ${object}`);
99+
}
100+
101+
const updatedRecord = {
102+
...table[index],
103+
...data,
104+
updated_at: new Date()
105+
};
106+
107+
table[index] = updatedRecord;
108+
return updatedRecord;
109+
}
110+
111+
async delete(object: string, id: string | number, options?: DriverOptions) {
112+
const table = this.getTable(object);
113+
const index = table.findIndex(r => r.id == id);
114+
115+
if (index === -1) return false;
116+
117+
table.splice(index, 1);
118+
return true;
119+
}
120+
121+
async count(object: string, query?: QueryAST, options?: DriverOptions) {
122+
return this.getTable(object).length;
123+
}
124+
125+
// ===================================
126+
// Bulk Operations
127+
// ===================================
128+
129+
async bulkCreate(object: string, dataArray: Record<string, any>[], options?: DriverOptions) {
130+
return Promise.all(dataArray.map(data => this.create(object, data, options)));
131+
}
132+
133+
async bulkUpdate(object: string, updates: { id: string | number, data: Record<string, any> }[], options?: DriverOptions) {
134+
return Promise.all(updates.map(u => this.update(object, u.id, u.data, options)));
135+
}
136+
137+
async bulkDelete(object: string, ids: (string | number)[], options?: DriverOptions) {
138+
await Promise.all(ids.map(id => this.delete(object, id, options)));
139+
}
140+
141+
// ===================================
142+
// Schema & Transactions
143+
// ===================================
144+
145+
async syncSchema(object: string, schema: any, options?: DriverOptions) {
146+
if (!this.db[object]) {
147+
this.db[object] = [];
148+
console.log(`✨ [InMemory] Created table: ${object}`);
149+
}
150+
}
151+
152+
async dropTable(object: string, options?: DriverOptions) {
153+
if (this.db[object]) {
154+
delete this.db[object];
155+
}
156+
}
157+
158+
async beginTransaction() {
159+
throw new Error('Transactions not supported in InMemoryDriver');
160+
}
161+
162+
async commit() { /* No-op */ }
163+
async rollback() { /* No-op */ }
164+
165+
// ===================================
166+
// Helpers
167+
// ===================================
168+
169+
private getTable(name: string) {
170+
if (!this.db[name]) {
171+
this.db[name] = [];
172+
}
173+
return this.db[name];
174+
}
175+
176+
private generateId() {
177+
return Math.random().toString(36).substring(2, 15);
178+
}
179+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"module": "commonjs",
5+
"declaration": true,
6+
"outDir": "./dist",
7+
"strict": true,
8+
"esModuleInterop": true,
9+
"skipLibCheck": true,
10+
"forceConsistentCasingInFileNames": true
11+
},
12+
"include": ["src/**/*", "objectstack.config.ts"]
13+
}

packages/spec/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export * from './system/territory.zod';
4747
export * from './system/license.zod';
4848
export * from './system/webhook.zod';
4949
export * from './system/translation.zod';
50+
export * from './system/driver.zod'; // Export Driver Protocol
5051
export * from './system/constants';
5152
export * from './system/types';
5253
export * from './system/discovery.zod';

0 commit comments

Comments
 (0)