@object-ui/core 0.3.1 → 0.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.
Files changed (68) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/dist/actions/index.d.ts +1 -1
  3. package/dist/actions/index.js +1 -1
  4. package/dist/evaluator/ExpressionCache.d.ts +101 -0
  5. package/dist/evaluator/ExpressionCache.js +135 -0
  6. package/dist/evaluator/ExpressionEvaluator.d.ts +20 -2
  7. package/dist/evaluator/ExpressionEvaluator.js +34 -14
  8. package/dist/evaluator/index.d.ts +3 -2
  9. package/dist/evaluator/index.js +3 -2
  10. package/dist/index.d.ts +10 -7
  11. package/dist/index.js +9 -7
  12. package/dist/query/index.d.ts +6 -0
  13. package/dist/query/index.js +6 -0
  14. package/dist/query/query-ast.d.ts +32 -0
  15. package/dist/query/query-ast.js +268 -0
  16. package/dist/registry/PluginScopeImpl.d.ts +80 -0
  17. package/dist/registry/PluginScopeImpl.js +243 -0
  18. package/dist/registry/PluginSystem.d.ts +66 -0
  19. package/dist/registry/PluginSystem.js +142 -0
  20. package/dist/registry/Registry.d.ts +73 -4
  21. package/dist/registry/Registry.js +112 -7
  22. package/dist/validation/index.d.ts +9 -0
  23. package/dist/validation/index.js +9 -0
  24. package/dist/validation/validation-engine.d.ts +70 -0
  25. package/dist/validation/validation-engine.js +363 -0
  26. package/dist/validation/validators/index.d.ts +16 -0
  27. package/dist/validation/validators/index.js +16 -0
  28. package/dist/validation/validators/object-validation-engine.d.ts +118 -0
  29. package/dist/validation/validators/object-validation-engine.js +538 -0
  30. package/package.json +13 -5
  31. package/src/actions/index.ts +1 -1
  32. package/src/evaluator/ExpressionCache.ts +192 -0
  33. package/src/evaluator/ExpressionEvaluator.ts +33 -14
  34. package/src/evaluator/__tests__/ExpressionCache.test.ts +135 -0
  35. package/src/evaluator/index.ts +3 -2
  36. package/src/index.ts +10 -7
  37. package/src/query/__tests__/query-ast.test.ts +211 -0
  38. package/src/query/__tests__/window-functions.test.ts +275 -0
  39. package/src/query/index.ts +7 -0
  40. package/src/query/query-ast.ts +341 -0
  41. package/src/registry/PluginScopeImpl.ts +259 -0
  42. package/src/registry/PluginSystem.ts +161 -0
  43. package/src/registry/Registry.ts +125 -8
  44. package/src/registry/__tests__/PluginSystem.test.ts +226 -0
  45. package/src/registry/__tests__/Registry.test.ts +293 -0
  46. package/src/registry/__tests__/plugin-scope-integration.test.ts +283 -0
  47. package/src/validation/__tests__/object-validation-engine.test.ts +567 -0
  48. package/src/validation/__tests__/validation-engine.test.ts +102 -0
  49. package/src/validation/index.ts +10 -0
  50. package/src/validation/validation-engine.ts +461 -0
  51. package/src/validation/validators/index.ts +25 -0
  52. package/src/validation/validators/object-validation-engine.ts +722 -0
  53. package/tsconfig.tsbuildinfo +1 -1
  54. package/vitest.config.ts +2 -0
  55. package/src/adapters/index.d.ts +0 -8
  56. package/src/adapters/index.js +0 -10
  57. package/src/builder/schema-builder.d.ts +0 -294
  58. package/src/builder/schema-builder.js +0 -503
  59. package/src/index.d.ts +0 -13
  60. package/src/index.js +0 -16
  61. package/src/registry/Registry.d.ts +0 -56
  62. package/src/registry/Registry.js +0 -43
  63. package/src/types/index.d.ts +0 -19
  64. package/src/types/index.js +0 -8
  65. package/src/utils/filter-converter.d.ts +0 -57
  66. package/src/utils/filter-converter.js +0 -100
  67. package/src/validation/schema-validator.d.ts +0 -94
  68. package/src/validation/schema-validator.js +0 -278
@@ -1,100 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- /**
9
- * Map MongoDB-like operators to ObjectStack filter operators.
10
- *
11
- * @param operator - MongoDB-style operator (e.g., '$gte', '$in')
12
- * @returns ObjectStack operator or null if not recognized
13
- */
14
- export function convertOperatorToAST(operator) {
15
- const operatorMap = {
16
- '$eq': '=',
17
- '$ne': '!=',
18
- '$gt': '>',
19
- '$gte': '>=',
20
- '$lt': '<',
21
- '$lte': '<=',
22
- '$in': 'in',
23
- '$nin': 'notin',
24
- '$notin': 'notin',
25
- '$contains': 'contains',
26
- '$startswith': 'startswith',
27
- '$between': 'between',
28
- };
29
- return operatorMap[operator] || null;
30
- }
31
- /**
32
- * Convert object-based filters to ObjectStack FilterNode AST format.
33
- * Converts MongoDB-like operators to ObjectStack filter expressions.
34
- *
35
- * @param filter - Object-based filter with optional operators
36
- * @returns FilterNode AST array
37
- *
38
- * @example
39
- * // Simple filter - converted to AST
40
- * convertFiltersToAST({ status: 'active' })
41
- * // => ['status', '=', 'active']
42
- *
43
- * @example
44
- * // Complex filter with operators
45
- * convertFiltersToAST({ age: { $gte: 18 } })
46
- * // => ['age', '>=', 18]
47
- *
48
- * @example
49
- * // Multiple conditions
50
- * convertFiltersToAST({ age: { $gte: 18, $lte: 65 }, status: 'active' })
51
- * // => ['and', ['age', '>=', 18], ['age', '<=', 65], ['status', '=', 'active']]
52
- *
53
- * @throws {Error} If an unknown operator is encountered
54
- */
55
- export function convertFiltersToAST(filter) {
56
- const conditions = [];
57
- for (const [field, value] of Object.entries(filter)) {
58
- if (value === null || value === undefined)
59
- continue;
60
- // Check if value is a complex operator object
61
- if (typeof value === 'object' && !Array.isArray(value)) {
62
- // Handle operator-based filters
63
- for (const [operator, operatorValue] of Object.entries(value)) {
64
- // Special handling for $regex - warn users about limited support
65
- if (operator === '$regex') {
66
- console.warn(`[ObjectUI] Warning: $regex operator is not fully supported. ` +
67
- `Converting to 'contains' which only supports substring matching, not regex patterns. ` +
68
- `Field: '${field}', Value: ${JSON.stringify(operatorValue)}. ` +
69
- `Consider using $contains or $startswith instead.`);
70
- conditions.push([field, 'contains', operatorValue]);
71
- continue;
72
- }
73
- const astOperator = convertOperatorToAST(operator);
74
- if (astOperator) {
75
- conditions.push([field, astOperator, operatorValue]);
76
- }
77
- else {
78
- // Unknown operator - throw error to avoid silent failure
79
- throw new Error(`[ObjectUI] Unknown filter operator '${operator}' for field '${field}'. ` +
80
- `Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, $startswith, $between. ` +
81
- `If you need exact object matching, use the value directly without an operator.`);
82
- }
83
- }
84
- }
85
- else {
86
- // Simple equality filter
87
- conditions.push([field, '=', value]);
88
- }
89
- }
90
- // If no conditions, return original filter
91
- if (conditions.length === 0) {
92
- return filter;
93
- }
94
- // If only one condition, return it directly
95
- if (conditions.length === 1) {
96
- return conditions[0];
97
- }
98
- // Multiple conditions: combine with 'and'
99
- return ['and', ...conditions];
100
- }
@@ -1,94 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- /**
9
- * @object-ui/core - Schema Validation
10
- *
11
- * Runtime validation utilities for Object UI schemas.
12
- * These utilities help ensure schemas are valid before rendering.
13
- *
14
- * @module validation
15
- * @packageDocumentation
16
- */
17
- import type { BaseSchema } from '@object-ui/types';
18
- /**
19
- * Validation error details
20
- */
21
- export interface ValidationError {
22
- path: string;
23
- message: string;
24
- type: 'error' | 'warning';
25
- code?: string;
26
- }
27
- /**
28
- * Validation result
29
- */
30
- export interface ValidationResult {
31
- valid: boolean;
32
- errors: ValidationError[];
33
- warnings: ValidationError[];
34
- }
35
- /**
36
- * Validate a complete schema
37
- *
38
- * @param schema - The schema to validate
39
- * @param options - Validation options
40
- * @returns Validation result with errors and warnings
41
- *
42
- * @example
43
- * ```typescript
44
- * const result = validateSchema({
45
- * type: 'form',
46
- * fields: [
47
- * { name: 'email', type: 'input' }
48
- * ]
49
- * });
50
- *
51
- * if (!result.valid) {
52
- * console.error('Validation errors:', result.errors);
53
- * }
54
- * ```
55
- */
56
- export declare function validateSchema(schema: any, path?: string): ValidationResult;
57
- /**
58
- * Assert that a schema is valid, throwing an error if not
59
- *
60
- * @param schema - The schema to validate
61
- * @throws Error if schema is invalid
62
- *
63
- * @example
64
- * ```typescript
65
- * try {
66
- * assertValidSchema(schema);
67
- * // Schema is valid, continue rendering
68
- * } catch (error) {
69
- * console.error('Invalid schema:', error.message);
70
- * }
71
- * ```
72
- */
73
- export declare function assertValidSchema(schema: any): asserts schema is BaseSchema;
74
- /**
75
- * Check if a value is a valid schema
76
- *
77
- * @param value - The value to check
78
- * @returns True if the value is a valid schema
79
- *
80
- * @example
81
- * ```typescript
82
- * if (isValidSchema(data)) {
83
- * renderSchema(data);
84
- * }
85
- * ```
86
- */
87
- export declare function isValidSchema(value: any): value is BaseSchema;
88
- /**
89
- * Get a human-readable error summary
90
- *
91
- * @param result - The validation result
92
- * @returns Formatted error summary
93
- */
94
- export declare function formatValidationErrors(result: ValidationResult): string;
@@ -1,278 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- /**
9
- * Validation rules for base schema
10
- */
11
- const BASE_SCHEMA_RULES = {
12
- type: {
13
- required: true,
14
- validate: (value) => typeof value === 'string' && value.length > 0,
15
- message: 'type must be a non-empty string'
16
- },
17
- id: {
18
- required: false,
19
- validate: (value) => typeof value === 'string',
20
- message: 'id must be a string'
21
- },
22
- className: {
23
- required: false,
24
- validate: (value) => typeof value === 'string',
25
- message: 'className must be a string'
26
- },
27
- visible: {
28
- required: false,
29
- validate: (value) => typeof value === 'boolean',
30
- message: 'visible must be a boolean'
31
- },
32
- disabled: {
33
- required: false,
34
- validate: (value) => typeof value === 'boolean',
35
- message: 'disabled must be a boolean'
36
- }
37
- };
38
- /**
39
- * Validate a schema against base rules
40
- */
41
- function validateBaseSchema(schema, path = 'schema') {
42
- const errors = [];
43
- if (!schema || typeof schema !== 'object') {
44
- errors.push({
45
- path,
46
- message: 'Schema must be an object',
47
- type: 'error',
48
- code: 'INVALID_SCHEMA'
49
- });
50
- return errors;
51
- }
52
- // Validate required and optional properties
53
- Object.entries(BASE_SCHEMA_RULES).forEach(([key, rule]) => {
54
- const value = schema[key];
55
- if (rule.required && value === undefined) {
56
- errors.push({
57
- path: `${path}.${key}`,
58
- message: `${key} is required`,
59
- type: 'error',
60
- code: 'MISSING_REQUIRED'
61
- });
62
- }
63
- if (value !== undefined && !rule.validate(value)) {
64
- errors.push({
65
- path: `${path}.${key}`,
66
- message: rule.message,
67
- type: 'error',
68
- code: 'INVALID_TYPE'
69
- });
70
- }
71
- });
72
- return errors;
73
- }
74
- /**
75
- * Validate CRUD schema specific properties
76
- */
77
- function validateCRUDSchema(schema, path = 'schema') {
78
- const errors = [];
79
- if (schema.type === 'crud') {
80
- // Check required properties for CRUD
81
- if (!schema.columns || !Array.isArray(schema.columns)) {
82
- errors.push({
83
- path: `${path}.columns`,
84
- message: 'CRUD schema requires columns array',
85
- type: 'error',
86
- code: 'MISSING_COLUMNS'
87
- });
88
- }
89
- if (!schema.api && !schema.dataSource) {
90
- errors.push({
91
- path: `${path}.api`,
92
- message: 'CRUD schema requires api or dataSource',
93
- type: 'warning',
94
- code: 'MISSING_DATA_SOURCE'
95
- });
96
- }
97
- // Validate columns
98
- if (schema.columns && Array.isArray(schema.columns)) {
99
- schema.columns.forEach((column, index) => {
100
- if (!column.name) {
101
- errors.push({
102
- path: `${path}.columns[${index}]`,
103
- message: 'Column requires name property',
104
- type: 'error',
105
- code: 'MISSING_COLUMN_NAME'
106
- });
107
- }
108
- });
109
- }
110
- // Validate fields if present
111
- if (schema.fields && Array.isArray(schema.fields)) {
112
- schema.fields.forEach((field, index) => {
113
- if (!field.name) {
114
- errors.push({
115
- path: `${path}.fields[${index}]`,
116
- message: 'Field requires name property',
117
- type: 'error',
118
- code: 'MISSING_FIELD_NAME'
119
- });
120
- }
121
- });
122
- }
123
- }
124
- return errors;
125
- }
126
- /**
127
- * Validate form schema specific properties
128
- */
129
- function validateFormSchema(schema, path = 'schema') {
130
- const errors = [];
131
- if (schema.type === 'form') {
132
- if (schema.fields && Array.isArray(schema.fields)) {
133
- schema.fields.forEach((field, index) => {
134
- if (!field.name) {
135
- errors.push({
136
- path: `${path}.fields[${index}]`,
137
- message: 'Form field requires name property',
138
- type: 'error',
139
- code: 'MISSING_FIELD_NAME'
140
- });
141
- }
142
- // Check for duplicate field names
143
- const duplicates = schema.fields.filter((f) => f.name === field.name);
144
- if (duplicates.length > 1) {
145
- errors.push({
146
- path: `${path}.fields[${index}]`,
147
- message: `Duplicate field name: ${field.name}`,
148
- type: 'warning',
149
- code: 'DUPLICATE_FIELD_NAME'
150
- });
151
- }
152
- });
153
- }
154
- }
155
- return errors;
156
- }
157
- /**
158
- * Validate child schemas recursively
159
- */
160
- function validateChildren(schema, path = 'schema') {
161
- const errors = [];
162
- const children = schema.children || schema.body;
163
- if (children) {
164
- if (Array.isArray(children)) {
165
- children.forEach((child, index) => {
166
- if (typeof child === 'object' && child !== null) {
167
- const childResult = validateSchema(child, `${path}.children[${index}]`);
168
- errors.push(...childResult.errors, ...childResult.warnings);
169
- }
170
- });
171
- }
172
- else if (typeof children === 'object' && children !== null) {
173
- const childResult = validateSchema(children, `${path}.children`);
174
- errors.push(...childResult.errors, ...childResult.warnings);
175
- }
176
- }
177
- return errors;
178
- }
179
- /**
180
- * Validate a complete schema
181
- *
182
- * @param schema - The schema to validate
183
- * @param options - Validation options
184
- * @returns Validation result with errors and warnings
185
- *
186
- * @example
187
- * ```typescript
188
- * const result = validateSchema({
189
- * type: 'form',
190
- * fields: [
191
- * { name: 'email', type: 'input' }
192
- * ]
193
- * });
194
- *
195
- * if (!result.valid) {
196
- * console.error('Validation errors:', result.errors);
197
- * }
198
- * ```
199
- */
200
- export function validateSchema(schema, path = 'schema') {
201
- const allErrors = [];
202
- // Validate base schema
203
- allErrors.push(...validateBaseSchema(schema, path));
204
- // Validate type-specific schemas
205
- allErrors.push(...validateCRUDSchema(schema, path));
206
- allErrors.push(...validateFormSchema(schema, path));
207
- // Validate children recursively
208
- allErrors.push(...validateChildren(schema, path));
209
- const errors = allErrors.filter(e => e.type === 'error');
210
- const warnings = allErrors.filter(e => e.type === 'warning');
211
- return {
212
- valid: errors.length === 0,
213
- errors,
214
- warnings
215
- };
216
- }
217
- /**
218
- * Assert that a schema is valid, throwing an error if not
219
- *
220
- * @param schema - The schema to validate
221
- * @throws Error if schema is invalid
222
- *
223
- * @example
224
- * ```typescript
225
- * try {
226
- * assertValidSchema(schema);
227
- * // Schema is valid, continue rendering
228
- * } catch (error) {
229
- * console.error('Invalid schema:', error.message);
230
- * }
231
- * ```
232
- */
233
- export function assertValidSchema(schema) {
234
- const result = validateSchema(schema);
235
- if (!result.valid) {
236
- const errorMessages = result.errors.map(e => `${e.path}: ${e.message}`).join('\n');
237
- throw new Error(`Schema validation failed:\n${errorMessages}`);
238
- }
239
- }
240
- /**
241
- * Check if a value is a valid schema
242
- *
243
- * @param value - The value to check
244
- * @returns True if the value is a valid schema
245
- *
246
- * @example
247
- * ```typescript
248
- * if (isValidSchema(data)) {
249
- * renderSchema(data);
250
- * }
251
- * ```
252
- */
253
- export function isValidSchema(value) {
254
- const result = validateSchema(value);
255
- return result.valid;
256
- }
257
- /**
258
- * Get a human-readable error summary
259
- *
260
- * @param result - The validation result
261
- * @returns Formatted error summary
262
- */
263
- export function formatValidationErrors(result) {
264
- const parts = [];
265
- if (result.errors.length > 0) {
266
- parts.push('Errors:');
267
- result.errors.forEach(error => {
268
- parts.push(` - ${error.path}: ${error.message}`);
269
- });
270
- }
271
- if (result.warnings.length > 0) {
272
- parts.push('Warnings:');
273
- result.warnings.forEach(warning => {
274
- parts.push(` - ${warning.path}: ${warning.message}`);
275
- });
276
- }
277
- return parts.join('\n');
278
- }