Skip to content

Commit 8211d64

Browse files
Copilothotlong
andcommitted
Phase 2 & 3: Decouple Validator and Formula engines from repository via plugin architecture
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 92d61ad commit 8211d64

4 files changed

Lines changed: 53 additions & 14 deletions

File tree

packages/foundation/core/src/formula-plugin.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ export class FormulaPlugin implements RuntimePlugin {
5353

5454
console.log(`[${this.name}] Installing formula plugin...`);
5555

56+
// Make formula engine accessible from the kernel for direct usage
57+
(kernel as any).formulaEngine = this.engine;
58+
5659
// Register formula provider if the kernel supports it
5760
this.registerFormulaProvider(kernel);
5861

packages/foundation/core/src/repository.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,41 @@ import { FormulaEngine } from './formula-engine';
1414
import { QueryBuilder } from './query';
1515

1616
export class ObjectRepository {
17-
private validator: Validator;
18-
private formulaEngine: FormulaEngine;
1917
private queryBuilder: QueryBuilder;
2018

2119
constructor(
2220
private objectName: string,
2321
private context: ObjectQLContext,
2422
private app: IObjectQL
2523
) {
26-
this.validator = new Validator();
27-
this.formulaEngine = new FormulaEngine();
2824
this.queryBuilder = new QueryBuilder();
2925
}
26+
27+
/**
28+
* Get validator instance from kernel (via plugin)
29+
* Falls back to creating a new instance if not available
30+
*/
31+
private getValidator(): Validator {
32+
const kernel = this.getKernel() as any;
33+
if (kernel.validator) {
34+
return kernel.validator;
35+
}
36+
// Fallback for backward compatibility
37+
return new Validator();
38+
}
39+
40+
/**
41+
* Get formula engine instance from kernel (via plugin)
42+
* Falls back to creating a new instance if not available
43+
*/
44+
private getFormulaEngine(): FormulaEngine {
45+
const kernel = this.getKernel() as any;
46+
if (kernel.formulaEngine) {
47+
return kernel.formulaEngine;
48+
}
49+
// Fallback for backward compatibility
50+
return new FormulaEngine();
51+
}
3052

3153
private getDriver(): Driver {
3254
const obj = this.getSchema();
@@ -106,7 +128,7 @@ export class ObjectRepository {
106128
}
107129

108130
const value = record[fieldName];
109-
const fieldResults = await this.validator.validateField(
131+
const fieldResults = await this.getValidator().validateField(
110132
fieldName,
111133
fieldConfig,
112134
value,
@@ -145,7 +167,7 @@ export class ObjectRepository {
145167
changedFields,
146168
};
147169

148-
const result = await this.validator.validate(schema.validation.rules, validationContext);
170+
const result = await this.getValidator().validate(schema.validation.rules, validationContext);
149171
allResults.push(...result.results);
150172
}
151173

@@ -192,7 +214,7 @@ export class ObjectRepository {
192214
// Evaluate each formula field
193215
for (const [fieldName, fieldConfig] of Object.entries(schema.fields)) {
194216
if (fieldConfig.type === 'formula' && fieldConfig.formula) {
195-
const result = this.formulaEngine.evaluate(
217+
const result = this.getFormulaEngine().evaluate(
196218
fieldConfig.formula,
197219
formulaContext,
198220
fieldConfig.data_type || 'text',

packages/foundation/core/src/validator-plugin.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ export class ValidatorPlugin implements RuntimePlugin {
6262

6363
console.log(`[${this.name}] Installing validator plugin...`);
6464

65+
// Make validator accessible from the kernel for direct usage
66+
(kernel as any).validator = this.validator;
67+
6568
// Register validation middleware for queries (if enabled)
6669
if (this.config.enableQueryValidation !== false) {
6770
this.registerQueryValidation(kernel);

packages/foundation/core/test/__mocks__/@objectstack/runtime.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,32 @@ class MockMetadataRegistry {
5757
class MockHookManager {
5858
private hooks = new Map<string, any[]>();
5959

60-
register(hookName: string, handler: any, packageName?: string): void {
60+
register(hookName: string, objectName: string, handler: any, packageName?: string): void {
6161
if (!this.hooks.has(hookName)) {
6262
this.hooks.set(hookName, []);
6363
}
64-
this.hooks.get(hookName)!.push({ handler, packageName });
64+
this.hooks.get(hookName)!.push({ objectName, handler, packageName });
6565
}
6666

67-
async trigger(hookName: string, context: any): Promise<void> {
67+
async trigger(hookName: string, objectName: string, context: any): Promise<void> {
6868
const handlers = this.hooks.get(hookName) || [];
69-
for (const { handler } of handlers) {
70-
await handler(context);
69+
for (const entry of handlers) {
70+
// Match on wildcard '*' or specific object name
71+
if (entry.objectName === '*' || entry.objectName === objectName) {
72+
await entry.handler(context);
73+
}
7174
}
7275
}
7376

74-
unregisterPackage(packageName: string): void {
77+
removePackage(packageName: string): void {
7578
for (const [hookName, handlers] of this.hooks.entries()) {
7679
this.hooks.set(hookName, handlers.filter(h => h.packageName !== packageName));
7780
}
7881
}
82+
83+
clear(): void {
84+
this.hooks.clear();
85+
}
7986
}
8087

8188
class MockActionManager {
@@ -100,7 +107,7 @@ class MockActionManager {
100107
return this.actions.get(key)?.handler;
101108
}
102109

103-
unregisterPackage(packageName: string): void {
110+
removePackage(packageName: string): void {
104111
const toDelete: string[] = [];
105112
for (const [key, action] of this.actions.entries()) {
106113
if (action.packageName === packageName) {
@@ -109,6 +116,10 @@ class MockActionManager {
109116
}
110117
toDelete.forEach(key => this.actions.delete(key));
111118
}
119+
120+
clear(): void {
121+
this.actions.clear();
122+
}
112123
}
113124

114125
export class ObjectStackKernel {

0 commit comments

Comments
 (0)