@objectstack/objectql 0.9.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +11 -375
- package/dist/engine.d.ts +67 -54
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +16 -0
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +33 -33
- package/dist/protocol.d.ts +19 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +31 -2
- package/dist/registry.d.ts +515 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +29 -0
- package/package.json +5 -4
- package/src/engine.test.ts +156 -0
- package/src/engine.ts +17 -0
- package/src/plugin.ts +2 -2
- package/src/protocol.ts +37 -2
- package/src/registry.ts +30 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @objectstack/objectql
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- Major version release for ObjectStack Protocol v1.0.
|
|
8
|
+
- Stabilized Protocol Definitions
|
|
9
|
+
- Enhanced Runtime Plugin Support
|
|
10
|
+
- Fixed Type Compliance across Monorepo
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @objectstack/spec@1.0.0
|
|
16
|
+
- @objectstack/core@1.0.0
|
|
17
|
+
- @objectstack/types@1.0.0
|
|
18
|
+
|
|
3
19
|
## 0.9.2
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,387 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @objectstack/objectql
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
The **Data Engine** for ObjectStack. It acts as a semantic layer between your application code and the underlying database.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **Middleware**: (Planned) Support for Hooks and Validators.
|
|
12
|
-
|
|
13
|
-
## 🤖 AI Development Context
|
|
14
|
-
|
|
15
|
-
**Role**: Data Engine / Query Layer
|
|
16
|
-
**Usage**:
|
|
17
|
-
- Use this package to execute data operations (`find`, `insert`).
|
|
18
|
-
- Do NOT bypass this layer to access drivers directly unless building a driver.
|
|
19
|
-
- This is the "Backend Brain" for data.
|
|
20
|
-
|
|
21
|
-
**Key Concepts**:
|
|
22
|
-
- `SchemaRegistry`: Holds all object definitions.
|
|
23
|
-
- `ObjectQL`: The main facade.
|
|
24
|
-
- `Driver`: Interface for storage adapters.
|
|
7
|
+
- **Universal API**: A consistent query interface (`find`, `insert`, `update`, `delete`) regardless of the storage backend.
|
|
8
|
+
- **Schema Validation**: Enforces Zod schemas defined in `@objectstack/spec`.
|
|
9
|
+
- **Query Resolution**: Translates ObjectStack queries into driver-specific commands.
|
|
10
|
+
- **Driver Architecture**: Pluggable storage (Memory, MongoDB, SQL, etc.).
|
|
25
11
|
|
|
26
12
|
## Usage
|
|
27
13
|
|
|
28
|
-
### 1. Standalone Usage
|
|
29
|
-
|
|
30
14
|
```typescript
|
|
31
15
|
import { ObjectQL } from '@objectstack/objectql';
|
|
32
|
-
import { InMemoryDriver } from '@objectstack/driver-memory'; // Note: Package name might export InMemoryDriver now
|
|
33
|
-
|
|
34
|
-
async function main() {
|
|
35
|
-
// 1. Initialize Engine
|
|
36
|
-
const ql = new ObjectQL();
|
|
37
|
-
|
|
38
|
-
// 2. Register Drivers
|
|
39
|
-
const memDriver = new InMemoryDriver({ name: 'default' });
|
|
40
|
-
ql.registerDriver(memDriver, true);
|
|
41
|
-
|
|
42
|
-
// 3. Load Schema (via Plugin/Manifest)
|
|
43
|
-
await ql.use({
|
|
44
|
-
name: 'my-app',
|
|
45
|
-
objects: [
|
|
46
|
-
{
|
|
47
|
-
name: 'todo',
|
|
48
|
-
fields: {
|
|
49
|
-
title: { type: 'text' },
|
|
50
|
-
completed: { type: 'boolean' }
|
|
51
|
-
},
|
|
52
|
-
datasource: 'default'
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
await ql.init();
|
|
58
|
-
|
|
59
|
-
// 4. Execute Queries
|
|
60
|
-
// Insert
|
|
61
|
-
await ql.insert('todo', { title: 'Buy Milk', completed: false });
|
|
62
|
-
|
|
63
|
-
// Find (Simple)
|
|
64
|
-
const todos = await ql.find('todo', { completed: false });
|
|
65
|
-
|
|
66
|
-
// Find (Advanced AST)
|
|
67
|
-
const results = await ql.find('todo', {
|
|
68
|
-
where: {
|
|
69
|
-
title: { $contains: 'Milk' }
|
|
70
|
-
},
|
|
71
|
-
limit: 10,
|
|
72
|
-
orderBy: [{ field: 'title', order: 'desc' }]
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
console.log(results);
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### 2. Using with ObjectKernel (Recommended)
|
|
80
|
-
|
|
81
|
-
When building full applications, use the `ObjectKernel` to manage plugins and configuration.
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { ObjectKernel } from '@objectstack/core';
|
|
85
|
-
import { DriverPlugin } from '@objectstack/runtime';
|
|
86
|
-
import { ObjectQLPlugin } from '@objectstack/objectql';
|
|
87
|
-
import { InMemoryDriver } from '@objectstack/driver-memory';
|
|
88
|
-
|
|
89
|
-
const kernel = new ObjectKernel();
|
|
90
|
-
|
|
91
|
-
// Register Engine and Drivers as Kernel Plugins
|
|
92
|
-
kernel.use(new ObjectQLPlugin())
|
|
93
|
-
.use(new DriverPlugin(new InMemoryDriver(), 'default'));
|
|
94
|
-
|
|
95
|
-
await kernel.bootstrap();
|
|
96
|
-
|
|
97
|
-
// The engine automatically discovers drivers and apps registered in the kernel.
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Architecture
|
|
101
|
-
|
|
102
|
-
- **SchemaRegistry**: Central store for all metadata (Objects, Apps, Config).
|
|
103
|
-
- **DriverRegistry**: Manages connections to physical data sources.
|
|
104
|
-
- **QueryPlanner**: (Internal) Normalizes simplified queries into `QueryAST`.
|
|
105
|
-
- **Executor**: Routes AST to the correct driver.
|
|
106
|
-
|
|
107
|
-
## Advanced Examples
|
|
108
|
-
|
|
109
|
-
### Complex Queries
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// Filtering with multiple conditions
|
|
113
|
-
const activeTasks = await ql.find('todo_task', {
|
|
114
|
-
where: {
|
|
115
|
-
$and: [
|
|
116
|
-
{ status: 'active' },
|
|
117
|
-
{ priority: { $gte: 3 } },
|
|
118
|
-
{ due_date: { $lte: new Date() } }
|
|
119
|
-
]
|
|
120
|
-
},
|
|
121
|
-
orderBy: [
|
|
122
|
-
{ field: 'priority', order: 'desc' },
|
|
123
|
-
{ field: 'due_date', order: 'asc' }
|
|
124
|
-
],
|
|
125
|
-
limit: 50
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// Text search
|
|
129
|
-
const searchResults = await ql.find('todo_task', {
|
|
130
|
-
where: {
|
|
131
|
-
$or: [
|
|
132
|
-
{ title: { $contains: 'urgent' } },
|
|
133
|
-
{ description: { $contains: 'urgent' } }
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// Nested conditions
|
|
139
|
-
const complexQuery = await ql.find('project', {
|
|
140
|
-
where: {
|
|
141
|
-
$and: [
|
|
142
|
-
{ status: { $in: ['active', 'planning'] } },
|
|
143
|
-
{
|
|
144
|
-
$or: [
|
|
145
|
-
{ budget: { $gt: 100000 } },
|
|
146
|
-
{ priority: { $eq: 1 } }
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
]
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### Batch Operations
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
// Batch insert
|
|
158
|
-
const newTasks = [
|
|
159
|
-
{ title: 'Task 1', priority: 1 },
|
|
160
|
-
{ title: 'Task 2', priority: 2 },
|
|
161
|
-
{ title: 'Task 3', priority: 3 }
|
|
162
|
-
];
|
|
163
|
-
|
|
164
|
-
for (const task of newTasks) {
|
|
165
|
-
await ql.insert('todo_task', task);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Batch update
|
|
169
|
-
const tasksToUpdate = await ql.find('todo_task', {
|
|
170
|
-
where: { status: 'pending' }
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
for (const task of tasksToUpdate) {
|
|
174
|
-
await ql.update('todo_task', task.id, {
|
|
175
|
-
status: 'in_progress',
|
|
176
|
-
started_at: new Date()
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### Working with Relationships
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
// One-to-Many: Get project with tasks
|
|
185
|
-
const project = await ql.find('project', {
|
|
186
|
-
where: { id: 'proj_123' },
|
|
187
|
-
include: ['tasks'] // Assumes 'tasks' is a relation field
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// Many-to-One: Get task with project details
|
|
191
|
-
const task = await ql.find('todo_task', {
|
|
192
|
-
where: { id: 'task_456' },
|
|
193
|
-
include: ['project']
|
|
194
|
-
});
|
|
195
16
|
|
|
196
|
-
//
|
|
197
|
-
const
|
|
198
|
-
|
|
17
|
+
// Querying data
|
|
18
|
+
const engine = kernel.getService('objectql');
|
|
19
|
+
const users = await engine.find('user', {
|
|
20
|
+
where: { role: 'admin' },
|
|
21
|
+
top: 10
|
|
199
22
|
});
|
|
200
|
-
|
|
201
|
-
const project = await ql.find('project', {
|
|
202
|
-
where: { id: 'proj_123' }
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const projectWithTasks = {
|
|
206
|
-
...project[0],
|
|
207
|
-
tasks: tasks
|
|
208
|
-
};
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Aggregations
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
// Count records
|
|
215
|
-
const totalTasks = await ql.count('todo_task', {
|
|
216
|
-
where: { status: 'active' }
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// Sum (if driver supports)
|
|
220
|
-
const totalBudget = await ql.aggregate('project', {
|
|
221
|
-
operation: 'sum',
|
|
222
|
-
field: 'budget',
|
|
223
|
-
where: { status: 'active' }
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Group by (if driver supports)
|
|
227
|
-
const tasksByStatus = await ql.aggregate('todo_task', {
|
|
228
|
-
operation: 'count',
|
|
229
|
-
groupBy: ['status']
|
|
230
|
-
});
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Multi-Datasource Queries
|
|
234
|
-
|
|
235
|
-
```typescript
|
|
236
|
-
import { PostgresDriver } from '@objectstack/driver-postgres';
|
|
237
|
-
import { MongoDBDriver } from '@objectstack/driver-mongodb';
|
|
238
|
-
import { RedisDriver } from '@objectstack/driver-redis';
|
|
239
|
-
|
|
240
|
-
const ql = new ObjectQL();
|
|
241
|
-
|
|
242
|
-
// Register multiple drivers
|
|
243
|
-
const pgDriver = new PostgresDriver({ connectionString: 'postgres://...' });
|
|
244
|
-
const mongoDriver = new MongoDBDriver({ url: 'mongodb://...' });
|
|
245
|
-
const redisDriver = new RedisDriver({ host: 'localhost' });
|
|
246
|
-
|
|
247
|
-
ql.registerDriver(pgDriver, false, 'postgres');
|
|
248
|
-
ql.registerDriver(mongoDriver, false, 'mongodb');
|
|
249
|
-
ql.registerDriver(redisDriver, false, 'redis');
|
|
250
|
-
|
|
251
|
-
// Configure objects to use different datasources
|
|
252
|
-
await ql.use({
|
|
253
|
-
name: 'multi-db-app',
|
|
254
|
-
objects: [
|
|
255
|
-
{
|
|
256
|
-
name: 'user',
|
|
257
|
-
datasource: 'postgres', // Users in PostgreSQL
|
|
258
|
-
fields: { /* ... */ }
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
name: 'product',
|
|
262
|
-
datasource: 'mongodb', // Products in MongoDB
|
|
263
|
-
fields: { /* ... */ }
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
name: 'session',
|
|
267
|
-
datasource: 'redis', // Sessions in Redis
|
|
268
|
-
fields: { /* ... */ }
|
|
269
|
-
}
|
|
270
|
-
]
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
await ql.init();
|
|
274
|
-
|
|
275
|
-
// Query automatically routes to correct datasource
|
|
276
|
-
const users = await ql.find('user'); // → PostgreSQL
|
|
277
|
-
const products = await ql.find('product'); // → MongoDB
|
|
278
|
-
const sessions = await ql.find('session'); // → Redis
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Custom Hooks and Middleware
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
// Register hooks for data operations
|
|
285
|
-
ql.registerHook('beforeInsert', async (ctx) => {
|
|
286
|
-
console.log(`Creating ${ctx.object}:`, ctx.data);
|
|
287
|
-
|
|
288
|
-
// Add timestamps
|
|
289
|
-
ctx.data.created_at = new Date();
|
|
290
|
-
ctx.data.updated_at = new Date();
|
|
291
|
-
|
|
292
|
-
// Validate
|
|
293
|
-
if (ctx.object === 'user' && !ctx.data.email) {
|
|
294
|
-
throw new Error('Email is required');
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
ql.registerHook('afterInsert', async (ctx) => {
|
|
299
|
-
console.log(`Created ${ctx.object}:`, ctx.result);
|
|
300
|
-
|
|
301
|
-
// Trigger events - get event bus from kernel or context
|
|
302
|
-
// Note: eventBus should be injected or accessed from context
|
|
303
|
-
const eventBus = ctx.getService?.('event-bus');
|
|
304
|
-
if (eventBus) {
|
|
305
|
-
await eventBus.emit('data:created', {
|
|
306
|
-
object: ctx.object,
|
|
307
|
-
id: ctx.result.id
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
ql.registerHook('beforeUpdate', async (ctx) => {
|
|
313
|
-
// Update timestamp
|
|
314
|
-
ctx.data.updated_at = new Date();
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
ql.registerHook('beforeDelete', async (ctx) => {
|
|
318
|
-
// Soft delete
|
|
319
|
-
if (ctx.object === 'user') {
|
|
320
|
-
throw new Error('Cannot delete users, use deactivate instead');
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### Transaction Support
|
|
326
|
-
|
|
327
|
-
```typescript
|
|
328
|
-
// If driver supports transactions
|
|
329
|
-
const driver = ql.getDriver('default');
|
|
330
|
-
|
|
331
|
-
if (driver.supports.transactions) {
|
|
332
|
-
await driver.beginTransaction();
|
|
333
|
-
|
|
334
|
-
try {
|
|
335
|
-
await ql.insert('order', {
|
|
336
|
-
customer_id: 'cust_123',
|
|
337
|
-
total: 100.00
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
await ql.update('inventory', 'inv_456', {
|
|
341
|
-
quantity: { $decrement: 1 }
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
await driver.commitTransaction();
|
|
345
|
-
} catch (error) {
|
|
346
|
-
await driver.rollbackTransaction();
|
|
347
|
-
throw error;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Schema Migration
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
// Add new field to existing object
|
|
356
|
-
const currentSchema = ql.getSchema('todo_task');
|
|
357
|
-
|
|
358
|
-
const updatedSchema = {
|
|
359
|
-
...currentSchema,
|
|
360
|
-
fields: {
|
|
361
|
-
...currentSchema.fields,
|
|
362
|
-
assignee: {
|
|
363
|
-
type: 'lookup',
|
|
364
|
-
reference: 'user',
|
|
365
|
-
label: 'Assignee'
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
// Re-register schema
|
|
371
|
-
ql.registerObject(updatedSchema);
|
|
372
|
-
|
|
373
|
-
// Driver might need to sync schema
|
|
374
|
-
const driver = ql.getDriver('default');
|
|
375
|
-
if (driver.syncSchema) {
|
|
376
|
-
await driver.syncSchema('todo_task', updatedSchema);
|
|
377
|
-
}
|
|
378
23
|
```
|
|
379
|
-
|
|
380
|
-
## Roadmap
|
|
381
|
-
|
|
382
|
-
- [x] Basic CRUD
|
|
383
|
-
- [x] Driver Routing
|
|
384
|
-
- [ ] Cross-Object Joins (Federation)
|
|
385
|
-
- [ ] Validation Layer (Zod)
|
|
386
|
-
- [ ] Access Control (ACL)
|
|
387
|
-
- [ ] Caching Layer
|
package/dist/engine.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export interface ObjectQLHostContext {
|
|
|
15
15
|
* ObjectQL Engine
|
|
16
16
|
*
|
|
17
17
|
* Implements the IDataEngine interface for data persistence.
|
|
18
|
+
* Acts as the reference implementation for:
|
|
19
|
+
* - CoreServiceName.data (CRUD)
|
|
20
|
+
* - CoreServiceName.metadata (Schema Registry)
|
|
18
21
|
*/
|
|
19
22
|
export declare class ObjectQL implements IDataEngine {
|
|
20
23
|
private drivers;
|
|
@@ -23,6 +26,16 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
23
26
|
private hooks;
|
|
24
27
|
private hostContext;
|
|
25
28
|
constructor(hostContext?: Record<string, any>);
|
|
29
|
+
/**
|
|
30
|
+
* Service Status Report
|
|
31
|
+
* Used by Kernel to verify health and capabilities.
|
|
32
|
+
*/
|
|
33
|
+
getStatus(): {
|
|
34
|
+
name: "data";
|
|
35
|
+
status: string;
|
|
36
|
+
version: string;
|
|
37
|
+
features: string[];
|
|
38
|
+
};
|
|
26
39
|
/**
|
|
27
40
|
* Expose the SchemaRegistry for plugins to register metadata
|
|
28
41
|
*/
|
|
@@ -50,13 +63,8 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
50
63
|
* Helper to get object definition
|
|
51
64
|
*/
|
|
52
65
|
getSchema(objectName: string): {
|
|
53
|
-
name: string;
|
|
54
|
-
active: boolean;
|
|
55
|
-
isSystem: boolean;
|
|
56
|
-
abstract: boolean;
|
|
57
|
-
datasource: string;
|
|
58
66
|
fields: Record<string, {
|
|
59
|
-
type: "number" | "boolean" | "
|
|
67
|
+
type: "number" | "boolean" | "code" | "date" | "lookup" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "file" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "json" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector";
|
|
60
68
|
required: boolean;
|
|
61
69
|
searchable: boolean;
|
|
62
70
|
multiple: boolean;
|
|
@@ -68,34 +76,52 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
68
76
|
encryption: boolean;
|
|
69
77
|
index: boolean;
|
|
70
78
|
externalId: boolean;
|
|
71
|
-
|
|
79
|
+
options?: {
|
|
80
|
+
value: string;
|
|
81
|
+
label: string;
|
|
82
|
+
color?: string | undefined;
|
|
83
|
+
default?: boolean | undefined;
|
|
84
|
+
}[] | undefined;
|
|
85
|
+
expression?: string | undefined;
|
|
86
|
+
defaultValue?: any;
|
|
87
|
+
min?: number | undefined;
|
|
88
|
+
max?: number | undefined;
|
|
89
|
+
step?: number | undefined;
|
|
90
|
+
language?: string | undefined;
|
|
91
|
+
encryptionConfig?: {
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
algorithm: "aes-256-gcm" | "aes-256-cbc" | "chacha20-poly1305";
|
|
94
|
+
keyManagement: {
|
|
95
|
+
provider: "local" | "aws-kms" | "azure-key-vault" | "gcp-kms" | "hashicorp-vault";
|
|
96
|
+
keyId?: string | undefined;
|
|
97
|
+
rotationPolicy?: {
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
frequencyDays: number;
|
|
100
|
+
retainOldVersions: number;
|
|
101
|
+
autoRotate: boolean;
|
|
102
|
+
} | undefined;
|
|
103
|
+
};
|
|
104
|
+
scope: "table" | "field" | "database" | "record";
|
|
105
|
+
deterministicEncryption: boolean;
|
|
106
|
+
searchableEncryption: boolean;
|
|
107
|
+
} | undefined;
|
|
108
|
+
formula?: string | undefined;
|
|
72
109
|
label?: string | undefined;
|
|
110
|
+
precision?: number | undefined;
|
|
111
|
+
name?: string | undefined;
|
|
73
112
|
description?: string | undefined;
|
|
74
113
|
format?: string | undefined;
|
|
75
|
-
defaultValue?: any;
|
|
76
114
|
maxLength?: number | undefined;
|
|
77
115
|
minLength?: number | undefined;
|
|
78
|
-
precision?: number | undefined;
|
|
79
116
|
scale?: number | undefined;
|
|
80
|
-
min?: number | undefined;
|
|
81
|
-
max?: number | undefined;
|
|
82
|
-
options?: {
|
|
83
|
-
label: string;
|
|
84
|
-
value: string;
|
|
85
|
-
color?: string | undefined;
|
|
86
|
-
default?: boolean | undefined;
|
|
87
|
-
}[] | undefined;
|
|
88
117
|
reference?: string | undefined;
|
|
89
118
|
referenceFilters?: string[] | undefined;
|
|
90
119
|
writeRequiresMasterRead?: boolean | undefined;
|
|
91
|
-
expression?: string | undefined;
|
|
92
|
-
formula?: string | undefined;
|
|
93
120
|
summaryOperations?: {
|
|
94
121
|
object: string;
|
|
122
|
+
function: "count" | "sum" | "avg" | "min" | "max";
|
|
95
123
|
field: string;
|
|
96
|
-
function: "min" | "max" | "count" | "sum" | "avg";
|
|
97
124
|
} | undefined;
|
|
98
|
-
language?: string | undefined;
|
|
99
125
|
theme?: string | undefined;
|
|
100
126
|
lineNumbers?: boolean | undefined;
|
|
101
127
|
maxRating?: number | undefined;
|
|
@@ -106,7 +132,6 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
106
132
|
colorFormat?: "hex" | "rgb" | "rgba" | "hsl" | undefined;
|
|
107
133
|
allowAlpha?: boolean | undefined;
|
|
108
134
|
presetColors?: string[] | undefined;
|
|
109
|
-
step?: number | undefined;
|
|
110
135
|
showValue?: boolean | undefined;
|
|
111
136
|
marks?: Record<string, string> | undefined;
|
|
112
137
|
barcodeFormat?: "qr" | "ean13" | "ean8" | "code128" | "code39" | "upca" | "upce" | undefined;
|
|
@@ -115,7 +140,7 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
115
140
|
allowScanning?: boolean | undefined;
|
|
116
141
|
currencyConfig?: {
|
|
117
142
|
precision: number;
|
|
118
|
-
currencyMode: "
|
|
143
|
+
currencyMode: "dynamic" | "fixed";
|
|
119
144
|
defaultCurrency: string;
|
|
120
145
|
} | undefined;
|
|
121
146
|
vectorConfig?: {
|
|
@@ -149,9 +174,9 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
149
174
|
storageBucket?: string | undefined;
|
|
150
175
|
storagePrefix?: string | undefined;
|
|
151
176
|
imageValidation?: {
|
|
177
|
+
autoRotate: boolean;
|
|
152
178
|
generateThumbnails: boolean;
|
|
153
179
|
preserveMetadata: boolean;
|
|
154
|
-
autoRotate: boolean;
|
|
155
180
|
minWidth?: number | undefined;
|
|
156
181
|
maxWidth?: number | undefined;
|
|
157
182
|
minHeight?: number | undefined;
|
|
@@ -166,26 +191,9 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
166
191
|
} | undefined;
|
|
167
192
|
maxVersions?: number | undefined;
|
|
168
193
|
} | undefined;
|
|
169
|
-
encryptionConfig?: {
|
|
170
|
-
enabled: boolean;
|
|
171
|
-
algorithm: "aes-256-gcm" | "aes-256-cbc" | "chacha20-poly1305";
|
|
172
|
-
keyManagement: {
|
|
173
|
-
provider: "local" | "aws-kms" | "azure-key-vault" | "gcp-kms" | "hashicorp-vault";
|
|
174
|
-
keyId?: string | undefined;
|
|
175
|
-
rotationPolicy?: {
|
|
176
|
-
enabled: boolean;
|
|
177
|
-
frequencyDays: number;
|
|
178
|
-
retainOldVersions: number;
|
|
179
|
-
autoRotate: boolean;
|
|
180
|
-
} | undefined;
|
|
181
|
-
};
|
|
182
|
-
scope: "field" | "table" | "record" | "database";
|
|
183
|
-
deterministicEncryption: boolean;
|
|
184
|
-
searchableEncryption: boolean;
|
|
185
|
-
} | undefined;
|
|
186
194
|
maskingRule?: {
|
|
187
195
|
field: string;
|
|
188
|
-
strategy: "
|
|
196
|
+
strategy: "partial" | "hash" | "redact" | "tokenize" | "randomize" | "nullify" | "substitute";
|
|
189
197
|
preserveFormat: boolean;
|
|
190
198
|
preserveLength: boolean;
|
|
191
199
|
pattern?: string | undefined;
|
|
@@ -207,18 +215,28 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
207
215
|
} | undefined;
|
|
208
216
|
} | undefined;
|
|
209
217
|
}>;
|
|
218
|
+
name: string;
|
|
219
|
+
active: boolean;
|
|
220
|
+
isSystem: boolean;
|
|
221
|
+
abstract: boolean;
|
|
222
|
+
datasource: string;
|
|
223
|
+
search?: {
|
|
224
|
+
fields: string[];
|
|
225
|
+
displayFields?: string[] | undefined;
|
|
226
|
+
filters?: string[] | undefined;
|
|
227
|
+
} | undefined;
|
|
228
|
+
tags?: string[] | undefined;
|
|
210
229
|
label?: string | undefined;
|
|
211
|
-
pluralLabel?: string | undefined;
|
|
212
230
|
description?: string | undefined;
|
|
231
|
+
pluralLabel?: string | undefined;
|
|
213
232
|
icon?: string | undefined;
|
|
214
|
-
tags?: string[] | undefined;
|
|
215
233
|
tableName?: string | undefined;
|
|
216
234
|
indexes?: {
|
|
217
|
-
fields: string[];
|
|
218
235
|
type: "hash" | "btree" | "gin" | "gist" | "fulltext";
|
|
236
|
+
fields: string[];
|
|
219
237
|
unique: boolean;
|
|
220
|
-
name?: string | undefined;
|
|
221
238
|
partial?: string | undefined;
|
|
239
|
+
name?: string | undefined;
|
|
222
240
|
}[] | undefined;
|
|
223
241
|
tenancy?: {
|
|
224
242
|
enabled: boolean;
|
|
@@ -245,20 +263,15 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
245
263
|
} | undefined;
|
|
246
264
|
cdc?: {
|
|
247
265
|
enabled: boolean;
|
|
248
|
-
events: ("
|
|
266
|
+
events: ("insert" | "update" | "delete")[];
|
|
249
267
|
destination: string;
|
|
250
268
|
} | undefined;
|
|
251
269
|
validations?: any[] | undefined;
|
|
252
270
|
titleFormat?: string | undefined;
|
|
253
271
|
compactLayout?: string[] | undefined;
|
|
254
|
-
search?: {
|
|
255
|
-
fields: string[];
|
|
256
|
-
displayFields?: string[] | undefined;
|
|
257
|
-
filters?: string[] | undefined;
|
|
258
|
-
} | undefined;
|
|
259
272
|
enable?: {
|
|
260
|
-
trackHistory: boolean;
|
|
261
273
|
searchable: boolean;
|
|
274
|
+
trackHistory: boolean;
|
|
262
275
|
apiEnabled: boolean;
|
|
263
276
|
files: boolean;
|
|
264
277
|
feeds: boolean;
|
|
@@ -266,7 +279,7 @@ export declare class ObjectQL implements IDataEngine {
|
|
|
266
279
|
trash: boolean;
|
|
267
280
|
mru: boolean;
|
|
268
281
|
clone: boolean;
|
|
269
|
-
apiMethods?: ("search" | "
|
|
282
|
+
apiMethods?: ("search" | "update" | "delete" | "get" | "list" | "create" | "upsert" | "bulk" | "aggregate" | "history" | "restore" | "purge" | "import" | "export")[] | undefined;
|
|
270
283
|
} | undefined;
|
|
271
284
|
} | undefined;
|
|
272
285
|
/**
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAgB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { createLogger } from '@objectstack/core';
|
|
2
|
+
import { CoreServiceName } from '@objectstack/spec/system';
|
|
2
3
|
import { SchemaRegistry } from './registry.js';
|
|
3
4
|
/**
|
|
4
5
|
* ObjectQL Engine
|
|
5
6
|
*
|
|
6
7
|
* Implements the IDataEngine interface for data persistence.
|
|
8
|
+
* Acts as the reference implementation for:
|
|
9
|
+
* - CoreServiceName.data (CRUD)
|
|
10
|
+
* - CoreServiceName.metadata (Schema Registry)
|
|
7
11
|
*/
|
|
8
12
|
export class ObjectQL {
|
|
9
13
|
constructor(hostContext = {}) {
|
|
@@ -23,6 +27,18 @@ export class ObjectQL {
|
|
|
23
27
|
this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });
|
|
24
28
|
this.logger.info('ObjectQL Engine Instance Created');
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Service Status Report
|
|
32
|
+
* Used by Kernel to verify health and capabilities.
|
|
33
|
+
*/
|
|
34
|
+
getStatus() {
|
|
35
|
+
return {
|
|
36
|
+
name: CoreServiceName.enum.data,
|
|
37
|
+
status: 'running',
|
|
38
|
+
version: '0.9.0',
|
|
39
|
+
features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']
|
|
40
|
+
};
|
|
41
|
+
}
|
|
26
42
|
/**
|
|
27
43
|
* Expose the SchemaRegistry for plugins to register metadata
|
|
28
44
|
*/
|