@objectql/core 1.3.1 → 1.5.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 +31 -0
- package/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.js +116 -0
- package/dist/app.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.js +98 -1
- package/dist/loader.js.map +1 -1
- package/dist/repository.d.ts +1 -0
- package/dist/repository.js +28 -3
- package/dist/repository.js.map +1 -1
- package/dist/validator.d.ts +69 -0
- package/dist/validator.js +461 -0
- package/dist/validator.js.map +1 -0
- package/jest.config.js +6 -1
- package/package.json +3 -3
- package/src/app.ts +96 -0
- package/src/index.ts +1 -0
- package/src/loader.ts +108 -1
- package/src/repository.ts +29 -3
- package/src/validator.ts +553 -0
- package/test/action.test.ts +240 -22
- package/test/fixtures/project-with-validation.object.yml +124 -0
- package/test/hook.test.ts +310 -27
- package/test/mock-driver.ts +6 -3
- package/test/validation.test.ts +486 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @objectql/core
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Minor version release - 1.5.0
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @objectql/driver-remote@1.5.0
|
|
13
|
+
- @objectql/types@1.5.0
|
|
14
|
+
|
|
15
|
+
## 1.4.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- Release version 1.4.0 with new features and enhancements:
|
|
20
|
+
- Added complete REST API implementation with CRUD operations
|
|
21
|
+
- Enhanced error handling with standardized error codes and HTTP status mapping
|
|
22
|
+
- Added AI context support for tracking intent and use cases
|
|
23
|
+
- Enhanced metadata API with detailed field information and action listing
|
|
24
|
+
- Improved JSON-RPC API with better error categorization
|
|
25
|
+
- Added hooks and actions validation and implementation
|
|
26
|
+
- Updated documentation and examples
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @objectql/driver-remote@1.4.0
|
|
32
|
+
- @objectql/types@1.4.0
|
|
33
|
+
|
|
3
34
|
## 1.3.1
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ObjectQL Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# @objectql/core
|
|
2
|
+
|
|
3
|
+
The core ORM and runtime engine for ObjectQL. This package handles object querying, CRUD operations, database driver coordination, transaction management, and **metadata-driven validation**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Unified Query Language**: A generic way to query data across different databases (SQL, Mongo, etc.).
|
|
8
|
+
- **Repository Pattern**: `ObjectRepository` for managing object records.
|
|
9
|
+
- **Driver Agnostic**: Abstraction layer for database drivers.
|
|
10
|
+
- **Dynamic Schema**: Loads object definitions from metadata.
|
|
11
|
+
- **Hooks & Actions**: Runtime logic injection.
|
|
12
|
+
- **Validation Engine**: Metadata-driven validation with field-level, cross-field, and state machine rules.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @objectql/core @objectql/types
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Basic Setup
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { ObjectQL } from '@objectql/core';
|
|
26
|
+
// Import a driver, e.g., @objectql/driver-knex
|
|
27
|
+
|
|
28
|
+
const objectql = new ObjectQL({
|
|
29
|
+
datasources: {
|
|
30
|
+
default: new MyDriver({ ... })
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await objectql.init();
|
|
35
|
+
|
|
36
|
+
// Use context for operations
|
|
37
|
+
const ctx = objectql.createContext({ userId: 'u-1' });
|
|
38
|
+
const projects = await ctx.object('project').find({
|
|
39
|
+
filters: [['status', '=', 'active']]
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Validation System
|
|
44
|
+
|
|
45
|
+
The validation system allows you to define validation rules in your object metadata and execute them programmatically.
|
|
46
|
+
|
|
47
|
+
#### Field-Level Validation
|
|
48
|
+
|
|
49
|
+
Define validation rules directly in field configuration:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { ObjectConfig } from '@objectql/types';
|
|
53
|
+
|
|
54
|
+
const projectObject: ObjectConfig = {
|
|
55
|
+
name: 'project',
|
|
56
|
+
fields: {
|
|
57
|
+
email: {
|
|
58
|
+
type: 'email',
|
|
59
|
+
required: true,
|
|
60
|
+
validation: {
|
|
61
|
+
format: 'email',
|
|
62
|
+
message: 'Please enter a valid email address'
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
budget: {
|
|
66
|
+
type: 'currency',
|
|
67
|
+
validation: {
|
|
68
|
+
min: 0,
|
|
69
|
+
max: 10000000,
|
|
70
|
+
message: 'Budget must be between 0 and 10,000,000'
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
name: {
|
|
74
|
+
type: 'text',
|
|
75
|
+
required: true,
|
|
76
|
+
validation: {
|
|
77
|
+
min_length: 3,
|
|
78
|
+
max_length: 100,
|
|
79
|
+
pattern: '^[a-zA-Z0-9\\s]+$',
|
|
80
|
+
message: 'Name must be 3-100 alphanumeric characters'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Using the Validator Class
|
|
88
|
+
|
|
89
|
+
Execute validation rules programmatically:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Validator } from '@objectql/core';
|
|
93
|
+
import { ValidationContext, CrossFieldValidationRule } from '@objectql/types';
|
|
94
|
+
|
|
95
|
+
// Create validator with optional language configuration
|
|
96
|
+
const validator = new Validator({
|
|
97
|
+
language: 'en',
|
|
98
|
+
languageFallback: ['en', 'zh-CN']
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Define cross-field validation rules
|
|
102
|
+
const rules: CrossFieldValidationRule[] = [
|
|
103
|
+
{
|
|
104
|
+
name: 'valid_date_range',
|
|
105
|
+
type: 'cross_field',
|
|
106
|
+
rule: {
|
|
107
|
+
field: 'end_date',
|
|
108
|
+
operator: '>=',
|
|
109
|
+
compare_to: 'start_date' // Cross-field comparison
|
|
110
|
+
},
|
|
111
|
+
message: 'End date must be on or after start date',
|
|
112
|
+
error_code: 'INVALID_DATE_RANGE'
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
// Validate a record
|
|
117
|
+
const context: ValidationContext = {
|
|
118
|
+
record: {
|
|
119
|
+
start_date: '2024-01-01',
|
|
120
|
+
end_date: '2024-12-31'
|
|
121
|
+
},
|
|
122
|
+
operation: 'create'
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const result = await validator.validate(rules, context);
|
|
126
|
+
|
|
127
|
+
if (!result.valid) {
|
|
128
|
+
console.log('Validation errors:', result.errors);
|
|
129
|
+
// Output: Array of ValidationRuleResult objects
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### State Machine Validation
|
|
134
|
+
|
|
135
|
+
Enforce valid state transitions:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { StateMachineValidationRule } from '@objectql/types';
|
|
139
|
+
|
|
140
|
+
const statusRule: StateMachineValidationRule = {
|
|
141
|
+
name: 'status_transition',
|
|
142
|
+
type: 'state_machine',
|
|
143
|
+
field: 'status',
|
|
144
|
+
transitions: {
|
|
145
|
+
planning: {
|
|
146
|
+
allowed_next: ['active', 'cancelled']
|
|
147
|
+
},
|
|
148
|
+
active: {
|
|
149
|
+
allowed_next: ['on_hold', 'completed', 'cancelled']
|
|
150
|
+
},
|
|
151
|
+
completed: {
|
|
152
|
+
allowed_next: [],
|
|
153
|
+
is_terminal: true
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
message: 'Invalid status transition from {{old_status}} to {{new_status}}',
|
|
157
|
+
error_code: 'INVALID_STATE_TRANSITION'
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Validate on update
|
|
161
|
+
const updateContext: ValidationContext = {
|
|
162
|
+
record: { status: 'completed' },
|
|
163
|
+
previousRecord: { status: 'active' },
|
|
164
|
+
operation: 'update'
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const result = await validator.validate([statusRule], updateContext);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Validation in Object Configuration
|
|
171
|
+
|
|
172
|
+
Add validation rules to your object metadata:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const projectConfig: ObjectConfig = {
|
|
176
|
+
name: 'project',
|
|
177
|
+
fields: {
|
|
178
|
+
// ... field definitions
|
|
179
|
+
},
|
|
180
|
+
validation: {
|
|
181
|
+
ai_context: {
|
|
182
|
+
intent: 'Ensure project data integrity',
|
|
183
|
+
validation_strategy: 'Fail fast with clear error messages'
|
|
184
|
+
},
|
|
185
|
+
rules: [
|
|
186
|
+
{
|
|
187
|
+
name: 'valid_date_range',
|
|
188
|
+
type: 'cross_field',
|
|
189
|
+
rule: {
|
|
190
|
+
field: 'end_date',
|
|
191
|
+
operator: '>=',
|
|
192
|
+
compare_to: 'start_date'
|
|
193
|
+
},
|
|
194
|
+
message: 'End date must be on or after start date',
|
|
195
|
+
error_code: 'INVALID_DATE_RANGE'
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'status_transition',
|
|
199
|
+
type: 'state_machine',
|
|
200
|
+
field: 'status',
|
|
201
|
+
transitions: {
|
|
202
|
+
planning: { allowed_next: ['active', 'cancelled'] },
|
|
203
|
+
active: { allowed_next: ['completed', 'cancelled'] }
|
|
204
|
+
},
|
|
205
|
+
message: 'Invalid status transition'
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### Validation Features
|
|
213
|
+
|
|
214
|
+
**Supported Validation Types:**
|
|
215
|
+
- `field` - Built-in field validation (required, format, min/max, length, pattern)
|
|
216
|
+
- `cross_field` - Validate relationships between fields
|
|
217
|
+
- `state_machine` - Enforce valid state transitions
|
|
218
|
+
- `unique` - Uniqueness validation (stub - requires database integration)
|
|
219
|
+
- `business_rule` - Complex business rules (stub - requires expression evaluation)
|
|
220
|
+
- `custom` - Custom validation logic (stub - requires safe function execution)
|
|
221
|
+
- `dependency` - Related record validation (stub - requires database integration)
|
|
222
|
+
|
|
223
|
+
**Comparison Operators:**
|
|
224
|
+
- `=`, `!=` - Equality/inequality
|
|
225
|
+
- `>`, `>=`, `<`, `<=` - Comparison
|
|
226
|
+
- `in`, `not_in` - Array membership
|
|
227
|
+
- `contains`, `not_contains` - String containment
|
|
228
|
+
- `starts_with`, `ends_with` - String prefix/suffix
|
|
229
|
+
|
|
230
|
+
**Validation Triggers:**
|
|
231
|
+
- `create` - Run on record creation
|
|
232
|
+
- `update` - Run on record update
|
|
233
|
+
- `delete` - Run on record deletion
|
|
234
|
+
|
|
235
|
+
**Severity Levels:**
|
|
236
|
+
- `error` - Blocks the operation
|
|
237
|
+
- `warning` - Shows warning but allows operation
|
|
238
|
+
- `info` - Informational message
|
|
239
|
+
|
|
240
|
+
**Advanced Features:**
|
|
241
|
+
- Field-specific triggers (validate only when specific fields change)
|
|
242
|
+
- Conditional validation with `apply_when`
|
|
243
|
+
- Template message formatting with `{{field}}` placeholders
|
|
244
|
+
- Internationalization support with language fallback
|
|
245
|
+
- AI context for documentation and LLM understanding
|
|
246
|
+
|
|
247
|
+
## Shared Metadata
|
|
248
|
+
|
|
249
|
+
You can pass an existing `MetadataRegistry` to ObjectQL:
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
const registry = new MetadataRegistry();
|
|
253
|
+
// ... pre-load metadata ...
|
|
254
|
+
|
|
255
|
+
const objectql = new ObjectQL({
|
|
256
|
+
registry: registry,
|
|
257
|
+
datasources: { ... }
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## API Reference
|
|
262
|
+
|
|
263
|
+
### Validator Class
|
|
264
|
+
|
|
265
|
+
**Constructor:**
|
|
266
|
+
```typescript
|
|
267
|
+
new Validator(options?: ValidatorOptions)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Options:**
|
|
271
|
+
- `language?: string` - Preferred language for validation messages (default: 'en')
|
|
272
|
+
- `languageFallback?: string[]` - Fallback languages (default: ['en', 'zh-CN'])
|
|
273
|
+
|
|
274
|
+
**Methods:**
|
|
275
|
+
|
|
276
|
+
- `validate(rules: AnyValidationRule[], context: ValidationContext): Promise<ValidationResult>`
|
|
277
|
+
- Executes validation rules against a record
|
|
278
|
+
- Returns validation result with errors, warnings, and info messages
|
|
279
|
+
|
|
280
|
+
- `validateField(fieldName: string, fieldConfig: FieldConfig, value: any, context: ValidationContext): Promise<ValidationRuleResult[]>`
|
|
281
|
+
- Validates a single field value
|
|
282
|
+
- Returns array of validation results
|
|
283
|
+
|
|
284
|
+
## See Also
|
|
285
|
+
|
|
286
|
+
- [@objectql/types](../types) - Type definitions including validation types
|
|
287
|
+
- [Validation Specification](../../docs/spec/validation.md) - Complete validation metadata specification
|
package/dist/app.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare class ObjectQL implements IObjectQL {
|
|
|
18
18
|
executeAction(objectName: string, actionName: string, ctx: ActionContext): Promise<any>;
|
|
19
19
|
loadFromDirectory(dir: string, packageName?: string): void;
|
|
20
20
|
addLoader(plugin: LoaderPlugin): void;
|
|
21
|
+
updateMetadata(type: string, id: string, content: any): Promise<void>;
|
|
21
22
|
createContext(options: ObjectQLContextOptions): ObjectQLContext;
|
|
22
23
|
registerObject(object: ObjectConfig): void;
|
|
23
24
|
unregisterObject(name: string): void;
|
|
@@ -25,4 +26,5 @@ export declare class ObjectQL implements IObjectQL {
|
|
|
25
26
|
getConfigs(): Record<string, ObjectConfig>;
|
|
26
27
|
datasource(name: string): Driver;
|
|
27
28
|
init(): Promise<void>;
|
|
29
|
+
private processInitialData;
|
|
28
30
|
}
|
package/dist/app.js
CHANGED
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.ObjectQL = void 0;
|
|
4
37
|
const types_1 = require("@objectql/types");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const yaml = __importStar(require("js-yaml"));
|
|
5
41
|
const loader_1 = require("./loader");
|
|
6
42
|
const repository_1 = require("./repository");
|
|
7
43
|
const plugin_1 = require("./plugin");
|
|
@@ -74,6 +110,45 @@ class ObjectQL {
|
|
|
74
110
|
addLoader(plugin) {
|
|
75
111
|
this.loader.use(plugin);
|
|
76
112
|
}
|
|
113
|
+
async updateMetadata(type, id, content) {
|
|
114
|
+
// Use registry to find the entry so we can get the file path
|
|
115
|
+
const entry = this.metadata.getEntry(type, id);
|
|
116
|
+
if (!entry) {
|
|
117
|
+
throw new Error(`Metadata ${type}:${id} not found`);
|
|
118
|
+
}
|
|
119
|
+
if (!entry.path) {
|
|
120
|
+
throw new Error('Cannot update: Metadata source file not found (in-memory only?)');
|
|
121
|
+
}
|
|
122
|
+
// Safety Check: Prevent writing to node_modules
|
|
123
|
+
if (entry.path.includes('node_modules')) {
|
|
124
|
+
throw new Error(`Cannot update metadata ${type}:${id}: File is inside node_modules (read-only package).`);
|
|
125
|
+
}
|
|
126
|
+
// Check file extension
|
|
127
|
+
const ext = path.extname(entry.path).toLowerCase();
|
|
128
|
+
let newContent = '';
|
|
129
|
+
if (ext === '.yml' || ext === '.yaml') {
|
|
130
|
+
newContent = yaml.dump(content);
|
|
131
|
+
}
|
|
132
|
+
else if (ext === '.json') {
|
|
133
|
+
newContent = JSON.stringify(content, null, 2);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
throw new Error(`Cannot update: Unsupported file format ${ext} (only .yml, .yaml, .json supported)`);
|
|
137
|
+
}
|
|
138
|
+
// Write file
|
|
139
|
+
try {
|
|
140
|
+
await fs.promises.chmod(entry.path, 0o666).catch(() => { }); // Try to ensure writable
|
|
141
|
+
await fs.promises.writeFile(entry.path, newContent, 'utf8');
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
throw new Error(`Failed to write file ${entry.path}: ${e.message}`);
|
|
145
|
+
}
|
|
146
|
+
// Update registry in-memory
|
|
147
|
+
entry.content = content;
|
|
148
|
+
// If it's an object update, we might need some re-processing?
|
|
149
|
+
// For now, assume a restart or reload is needed for deep schema changes,
|
|
150
|
+
// but simple property updates are reflected immediately in registry.
|
|
151
|
+
}
|
|
77
152
|
createContext(options) {
|
|
78
153
|
const ctx = {
|
|
79
154
|
userId: options.userId,
|
|
@@ -205,6 +280,47 @@ class ObjectQL {
|
|
|
205
280
|
await driver.init(objects);
|
|
206
281
|
}
|
|
207
282
|
}
|
|
283
|
+
// 6. Process Initial Data
|
|
284
|
+
await this.processInitialData();
|
|
285
|
+
}
|
|
286
|
+
async processInitialData() {
|
|
287
|
+
const dataEntries = this.metadata.list('data');
|
|
288
|
+
if (dataEntries.length === 0)
|
|
289
|
+
return;
|
|
290
|
+
console.log(`Processing ${dataEntries.length} initial data files...`);
|
|
291
|
+
// We need a system context to write data
|
|
292
|
+
const ctx = this.createContext({ isSystem: true });
|
|
293
|
+
for (const entry of dataEntries) {
|
|
294
|
+
// Expected format:
|
|
295
|
+
// object: User
|
|
296
|
+
// records:
|
|
297
|
+
// - name: Admin
|
|
298
|
+
// email: admin@example.com
|
|
299
|
+
const objectName = entry.object;
|
|
300
|
+
const records = entry.records;
|
|
301
|
+
if (!objectName || !records || !Array.isArray(records)) {
|
|
302
|
+
console.warn(`Skipping invalid data entry:`, entry);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const repo = ctx.object(objectName);
|
|
306
|
+
for (const record of records) {
|
|
307
|
+
try {
|
|
308
|
+
// Check existence if a unique key is provided?
|
|
309
|
+
// For now, let's assume if it has an ID, we check it.
|
|
310
|
+
// Or we could try to find existing record by some key matching logic.
|
|
311
|
+
// Simple approach: create. If it fails (constraint), ignore.
|
|
312
|
+
// Actually, a better approach for initial data is "upsert" or "create if not exists".
|
|
313
|
+
// But without unique keys defined in data, we can't reliably dedup.
|
|
314
|
+
// Let's try to 'create' and catch errors.
|
|
315
|
+
await repo.create(record);
|
|
316
|
+
console.log(`Initialized record for ${objectName}`);
|
|
317
|
+
}
|
|
318
|
+
catch (e) {
|
|
319
|
+
// Ignore duplicate key errors silently-ish
|
|
320
|
+
// console.warn(`Failed to insert initial data for ${objectName}: ${e.message}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
208
324
|
}
|
|
209
325
|
}
|
|
210
326
|
exports.ObjectQL = ObjectQL;
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -23,4 +23,5 @@ __exportStar(require("./remote"), exports);
|
|
|
23
23
|
__exportStar(require("./action"), exports);
|
|
24
24
|
__exportStar(require("./hook"), exports);
|
|
25
25
|
__exportStar(require("./object"), exports);
|
|
26
|
+
__exportStar(require("./validator"), exports);
|
|
26
27
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,+CAA6B;AAC7B,wCAAsB;AACtB,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,+CAA6B;AAC7B,wCAAsB;AACtB,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB;AACzB,8CAA4B"}
|
package/dist/loader.js
CHANGED
|
@@ -133,6 +133,48 @@ class ObjectLoader {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
|
+
// Generic YAML Metadata Loaders
|
|
137
|
+
const metaTypes = ['view', 'form', 'menu', 'permission', 'report', 'workflow', 'validation', 'data'];
|
|
138
|
+
for (const type of metaTypes) {
|
|
139
|
+
this.use({
|
|
140
|
+
name: type,
|
|
141
|
+
glob: [`**/*.${type}.yml`, `**/*.${type}.yaml`],
|
|
142
|
+
handler: (ctx) => {
|
|
143
|
+
try {
|
|
144
|
+
const doc = yaml.load(ctx.content);
|
|
145
|
+
if (!doc)
|
|
146
|
+
return;
|
|
147
|
+
// Use 'name' from doc, or filename base (without extension)
|
|
148
|
+
let id = doc.name;
|
|
149
|
+
if (!id && type !== 'data') {
|
|
150
|
+
const basename = path.basename(ctx.file);
|
|
151
|
+
// e.g. "my-view.view.yml" -> "my-view"
|
|
152
|
+
// Regex: remove .type.yml or .type.yaml
|
|
153
|
+
const re = new RegExp(`\\.${type}\\.(yml|yaml)$`);
|
|
154
|
+
id = basename.replace(re, '');
|
|
155
|
+
}
|
|
156
|
+
// Data entries might not need a name, but for registry we need an ID.
|
|
157
|
+
// For data, we can use filename if not present.
|
|
158
|
+
if (!id && type === 'data') {
|
|
159
|
+
id = path.basename(ctx.file);
|
|
160
|
+
}
|
|
161
|
+
// Ensure name is in the doc for consistency
|
|
162
|
+
if (!doc.name)
|
|
163
|
+
doc.name = id;
|
|
164
|
+
ctx.registry.register(type, {
|
|
165
|
+
type: type,
|
|
166
|
+
id: id,
|
|
167
|
+
path: ctx.file,
|
|
168
|
+
package: ctx.packageName,
|
|
169
|
+
content: doc
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
console.error(`Error loading ${type} from ${ctx.file}:`, e);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
136
178
|
}
|
|
137
179
|
use(plugin) {
|
|
138
180
|
this.plugins.push(plugin);
|
|
@@ -156,9 +198,35 @@ class ObjectLoader {
|
|
|
156
198
|
}
|
|
157
199
|
}
|
|
158
200
|
runPlugin(plugin, dir, packageName) {
|
|
201
|
+
// Enforce path conventions:
|
|
202
|
+
// 1. Never scan node_modules (unless explicitly loaded via loadPackage which sets cwd inside it)
|
|
203
|
+
// 2. Ignore build artifacts (dist, build, out) to avoid double-loading metadata if both src and dist exist.
|
|
204
|
+
// Note: If you want to load from 'dist', you must explicitly point the loader to it (e.g. loader.load('./dist')).
|
|
205
|
+
// In that case, the patterns won't match relative to the CWD.
|
|
206
|
+
// Path conventions:
|
|
207
|
+
// 1. Always ignore node_modules and .git
|
|
208
|
+
const ignore = [
|
|
209
|
+
'**/node_modules/**',
|
|
210
|
+
'**/.git/**'
|
|
211
|
+
];
|
|
212
|
+
// 2. Intelligent handling of build artifacts (dist/build)
|
|
213
|
+
// If 'src' exists in the scan directory, we assume it's a Development Environment.
|
|
214
|
+
// In Dev, we ignore 'dist' to avoid duplicate loading (ts in src vs js in dist).
|
|
215
|
+
// In Production (no src), we must NOT ignore 'dist', otherwise we can't load compiled hooks/actions.
|
|
216
|
+
const srcPath = path.join(dir, 'src');
|
|
217
|
+
const hasSrc = fs.existsSync(srcPath) && fs.statSync(srcPath).isDirectory();
|
|
218
|
+
if (hasSrc) {
|
|
219
|
+
ignore.push('**/dist/**', '**/build/**', '**/out/**');
|
|
220
|
+
}
|
|
221
|
+
// 3. User instruction: "src 不行的" (src is not viable for metadata in production)
|
|
222
|
+
// Metadata (.yml) should ideally be placed in 'objects/' or root, not 'src/',
|
|
223
|
+
// to simplify packaging (so you don't need to copy assets from src to dist).
|
|
224
|
+
// However, we do not strictly block 'src' scanning here to avoid breaking dev workflow.
|
|
225
|
+
// The exclusion of 'dist' in dev mode (above) handles the code duality.
|
|
159
226
|
const files = glob.sync(plugin.glob, {
|
|
160
227
|
cwd: dir,
|
|
161
|
-
absolute: true
|
|
228
|
+
absolute: true,
|
|
229
|
+
ignore
|
|
162
230
|
});
|
|
163
231
|
for (const file of files) {
|
|
164
232
|
try {
|
|
@@ -192,6 +260,35 @@ function registerObject(registry, obj, file, packageName) {
|
|
|
192
260
|
}
|
|
193
261
|
}
|
|
194
262
|
}
|
|
263
|
+
// Check for existing object to Merge
|
|
264
|
+
const existing = registry.getEntry('object', obj.name);
|
|
265
|
+
if (existing) {
|
|
266
|
+
const base = existing.content;
|
|
267
|
+
// Merge Fields: New fields overwrite old ones
|
|
268
|
+
if (obj.fields) {
|
|
269
|
+
base.fields = { ...base.fields, ...obj.fields };
|
|
270
|
+
}
|
|
271
|
+
// Merge Actions
|
|
272
|
+
if (obj.actions) {
|
|
273
|
+
base.actions = { ...base.actions, ...obj.actions };
|
|
274
|
+
}
|
|
275
|
+
// Merge Indexes
|
|
276
|
+
if (obj.indexes) {
|
|
277
|
+
base.indexes = { ...base.indexes, ...obj.indexes };
|
|
278
|
+
}
|
|
279
|
+
// Override Top-level Properties if provided
|
|
280
|
+
if (obj.label)
|
|
281
|
+
base.label = obj.label;
|
|
282
|
+
if (obj.icon)
|
|
283
|
+
base.icon = obj.icon;
|
|
284
|
+
if (obj.description)
|
|
285
|
+
base.description = obj.description;
|
|
286
|
+
if (obj.datasource)
|
|
287
|
+
base.datasource = obj.datasource;
|
|
288
|
+
// Update the content reference
|
|
289
|
+
existing.content = base;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
195
292
|
registry.register('object', {
|
|
196
293
|
type: 'object',
|
|
197
294
|
id: obj.name,
|