rhales 0.4.0 → 0.5.3
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.
- checksums.yaml +4 -4
- data/.github/renovate.json5 +52 -0
- data/.github/workflows/ci.yml +123 -0
- data/.github/workflows/claude-code-review.yml +69 -0
- data/.github/workflows/claude.yml +49 -0
- data/.github/workflows/code-smells.yml +146 -0
- data/.github/workflows/ruby-lint.yml +78 -0
- data/.github/workflows/yardoc.yml +126 -0
- data/.gitignore +55 -0
- data/.pr_agent.toml +63 -0
- data/.pre-commit-config.yaml +89 -0
- data/.prettierignore +8 -0
- data/.prettierrc +38 -0
- data/.reek.yml +98 -0
- data/.rubocop.yml +428 -0
- data/.serena/.gitignore +3 -0
- data/.yardopts +56 -0
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +1 -1
- data/Gemfile +29 -0
- data/Gemfile.lock +189 -0
- data/README.md +686 -868
- data/Rakefile +46 -0
- data/debug_context.rb +25 -0
- data/demo/rhales-roda-demo/.gitignore +7 -0
- data/demo/rhales-roda-demo/Gemfile +32 -0
- data/demo/rhales-roda-demo/Gemfile.lock +151 -0
- data/demo/rhales-roda-demo/MAIL.md +405 -0
- data/demo/rhales-roda-demo/README.md +376 -0
- data/demo/rhales-roda-demo/RODA-TEMPLATE-ENGINES.md +192 -0
- data/demo/rhales-roda-demo/Rakefile +49 -0
- data/demo/rhales-roda-demo/app.rb +325 -0
- data/demo/rhales-roda-demo/bin/rackup +26 -0
- data/demo/rhales-roda-demo/config.ru +13 -0
- data/demo/rhales-roda-demo/db/migrate/001_create_rodauth_tables.rb +266 -0
- data/demo/rhales-roda-demo/db/migrate/002_create_rodauth_password_tables.rb +79 -0
- data/demo/rhales-roda-demo/db/migrate/003_add_admin_account.rb +68 -0
- data/demo/rhales-roda-demo/templates/change_login.rue +31 -0
- data/demo/rhales-roda-demo/templates/change_password.rue +36 -0
- data/demo/rhales-roda-demo/templates/close_account.rue +31 -0
- data/demo/rhales-roda-demo/templates/create_account.rue +40 -0
- data/demo/rhales-roda-demo/templates/dashboard.rue +150 -0
- data/demo/rhales-roda-demo/templates/home.rue +78 -0
- data/demo/rhales-roda-demo/templates/layouts/main.rue +168 -0
- data/demo/rhales-roda-demo/templates/login.rue +65 -0
- data/demo/rhales-roda-demo/templates/logout.rue +25 -0
- data/demo/rhales-roda-demo/templates/reset_password.rue +26 -0
- data/demo/rhales-roda-demo/templates/verify_account.rue +27 -0
- data/demo/rhales-roda-demo/test_full_output.rb +27 -0
- data/demo/rhales-roda-demo/test_simple.rb +24 -0
- data/docs/.gitignore +9 -0
- data/docs/architecture/data-flow.md +499 -0
- data/examples/dashboard-with-charts.rue +271 -0
- data/examples/form-with-validation.rue +180 -0
- data/examples/simple-page.rue +61 -0
- data/examples/vue.rue +136 -0
- data/generate-json-schemas.ts +158 -0
- data/json_schemer_migration_summary.md +172 -0
- data/lib/rhales/adapters/base_auth.rb +2 -0
- data/lib/rhales/adapters/base_request.rb +2 -0
- data/lib/rhales/adapters/base_session.rb +2 -0
- data/lib/rhales/adapters.rb +7 -0
- data/lib/rhales/configuration.rb +47 -0
- data/lib/rhales/core/context.rb +354 -0
- data/lib/rhales/{rue_document.rb → core/rue_document.rb} +56 -38
- data/lib/rhales/{template_engine.rb → core/template_engine.rb} +66 -59
- data/lib/rhales/{view.rb → core/view.rb} +112 -135
- data/lib/rhales/{view_composition.rb → core/view_composition.rb} +78 -8
- data/lib/rhales/core.rb +9 -0
- data/lib/rhales/errors/hydration_collision_error.rb +2 -0
- data/lib/rhales/errors.rb +2 -0
- data/lib/rhales/{earliest_injection_detector.rb → hydration/earliest_injection_detector.rb} +4 -0
- data/lib/rhales/hydration/hydration_data_aggregator.rb +487 -0
- data/lib/rhales/{hydration_endpoint.rb → hydration/hydration_endpoint.rb} +16 -12
- data/lib/rhales/{hydration_injector.rb → hydration/hydration_injector.rb} +4 -0
- data/lib/rhales/{hydration_registry.rb → hydration/hydration_registry.rb} +2 -0
- data/lib/rhales/hydration/hydrator.rb +102 -0
- data/lib/rhales/{link_based_injection_detector.rb → hydration/link_based_injection_detector.rb} +4 -0
- data/lib/rhales/{mount_point_detector.rb → hydration/mount_point_detector.rb} +4 -0
- data/lib/rhales/{safe_injection_validator.rb → hydration/safe_injection_validator.rb} +4 -0
- data/lib/rhales/hydration.rb +13 -0
- data/lib/rhales/{refinements → integrations/refinements}/require_refinements.rb +3 -1
- data/lib/rhales/{tilt.rb → integrations/tilt.rb} +22 -15
- data/lib/rhales/integrations.rb +6 -0
- data/lib/rhales/middleware/json_responder.rb +191 -0
- data/lib/rhales/middleware/schema_validator.rb +300 -0
- data/lib/rhales/middleware.rb +6 -0
- data/lib/rhales/parsers/handlebars_parser.rb +2 -0
- data/lib/rhales/parsers/rue_format_parser.rb +9 -7
- data/lib/rhales/parsers.rb +9 -0
- data/lib/rhales/{csp.rb → security/csp.rb} +27 -3
- data/lib/rhales/utils/json_serializer.rb +114 -0
- data/lib/rhales/utils/logging_helpers.rb +75 -0
- data/lib/rhales/utils/schema_extractor.rb +132 -0
- data/lib/rhales/utils/schema_generator.rb +194 -0
- data/lib/rhales/utils.rb +40 -0
- data/lib/rhales/version.rb +3 -1
- data/lib/rhales.rb +41 -24
- data/lib/tasks/rhales_schema.rake +197 -0
- data/package.json +10 -0
- data/pnpm-lock.yaml +345 -0
- data/pnpm-workspace.yaml +2 -0
- data/proofs/error_handling.rb +79 -0
- data/proofs/expanded_object_inheritance.rb +82 -0
- data/proofs/partial_context_scoping_fix.rb +168 -0
- data/proofs/ui_context_partial_inheritance.rb +236 -0
- data/rhales.gemspec +14 -6
- data/schema_vs_data_comparison.md +254 -0
- data/test_direct_access.rb +36 -0
- metadata +141 -23
- data/CLAUDE.locale.txt +0 -7
- data/lib/rhales/context.rb +0 -239
- data/lib/rhales/hydration_data_aggregator.rb +0 -221
- data/lib/rhales/hydrator.rb +0 -141
- data/lib/rhales/parsers/handlebars-grammar-review.txt +0 -39
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env -S pnpm exec tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate JSON Schemas and TypeScript types from Zod configuration schemas
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* pnpm exec tsx scripts/generate-json-schemas.ts # Generate main schema + types
|
|
8
|
+
* pnpm exec tsx scripts/generate-json-schemas.ts --openapi # Include OpenAPI schemas
|
|
9
|
+
* pnpm exec tsx scripts/generate-json-schemas.ts --watch # Watch mode (future)
|
|
10
|
+
*
|
|
11
|
+
* NOTE: The `-S` flag in the hasbang allows `env` to handle multiple arguments.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { writeFileSync, mkdirSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { z } from 'zod/v4';
|
|
17
|
+
import { configSchema as mutableConfigSchema } from '../schemas/config/mutable';
|
|
18
|
+
import { configSchema as staticConfigSchema } from '../schemas/config/static';
|
|
19
|
+
import { configSchema as runtimeConfigSchema } from '../schemas/config/runtime';
|
|
20
|
+
|
|
21
|
+
const ONETIME_HOME = process.env.ONETIME_HOME || process.cwd();
|
|
22
|
+
|
|
23
|
+
const OUTPUT_MAIN_SCHEMA = join(ONETIME_HOME, 'public/web/dist/schemas/runtime.schema.json');
|
|
24
|
+
const OUTPUT_SCHEMAS_DIR = join(ONETIME_HOME, 'etc/schemas');
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generate individual JSON schema files
|
|
28
|
+
*/
|
|
29
|
+
function generateIndividualSchemas(): void {
|
|
30
|
+
mkdirSync(OUTPUT_SCHEMAS_DIR, { recursive: true });
|
|
31
|
+
|
|
32
|
+
const schemas = [
|
|
33
|
+
{
|
|
34
|
+
schema: staticConfigSchema,
|
|
35
|
+
name: 'config.schema',
|
|
36
|
+
description: 'Static configuration settings loaded from config.yaml',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
schema: mutableConfigSchema,
|
|
40
|
+
name: 'mutable.schema',
|
|
41
|
+
description: 'Dynamic mutable config loaded from mutable.yaml',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
schema: runtimeConfigSchema,
|
|
45
|
+
name: 'runtime.schema',
|
|
46
|
+
description: 'Combined configuration schema for both static and mutable config',
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
schemas.forEach(({ schema, name, description }) => {
|
|
51
|
+
const jsonSchema = z.toJSONSchema(schema, {
|
|
52
|
+
target: 'draft-2020-12',
|
|
53
|
+
unrepresentable: 'any',
|
|
54
|
+
cycles: 'ref',
|
|
55
|
+
reused: 'inline',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const schemaWithMeta = {
|
|
59
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
60
|
+
$id: `https://onetimesecret.com/schemas/${name}.json`,
|
|
61
|
+
title: name
|
|
62
|
+
.split('-')
|
|
63
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
64
|
+
.join(' '),
|
|
65
|
+
description,
|
|
66
|
+
...jsonSchema,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const outputPath = join(OUTPUT_SCHEMAS_DIR, `${name}.json`);
|
|
70
|
+
writeFileSync(outputPath, JSON.stringify(schemaWithMeta, null, 2) + '\n');
|
|
71
|
+
console.log(`Generated: ${outputPath}`);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Generate main configuration schema as YAML
|
|
77
|
+
*/
|
|
78
|
+
function generateMainSchema(): void {
|
|
79
|
+
const jsonSchema = z.toJSONSchema(staticConfigSchema, {
|
|
80
|
+
target: 'draft-2020-12',
|
|
81
|
+
unrepresentable: 'any',
|
|
82
|
+
cycles: 'ref',
|
|
83
|
+
reused: 'inline',
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const schemaWithMeta = {
|
|
87
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
88
|
+
$id: 'https://onetimesecret.com/schemas/config.schema.json',
|
|
89
|
+
title: 'OneTimeSecret Configuration',
|
|
90
|
+
description: 'Configuration schema for OneTimeSecret application',
|
|
91
|
+
...jsonSchema,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
mkdirSync(join(OUTPUT_MAIN_SCHEMA, '..'), { recursive: true });
|
|
95
|
+
writeFileSync(OUTPUT_MAIN_SCHEMA, JSON.stringify(schemaWithMeta, null, 2) + '\n');
|
|
96
|
+
console.log(`Generated: ${OUTPUT_MAIN_SCHEMA}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Generate OpenAPI schemas (optional)
|
|
101
|
+
*/
|
|
102
|
+
function generateOpenAPISchemas(): void {
|
|
103
|
+
const schemas = [
|
|
104
|
+
{ schema: staticConfigSchema, name: 'static' },
|
|
105
|
+
{ schema: mutableConfigSchema, name: 'mutable' },
|
|
106
|
+
{ schema: runtimeConfigSchema, name: 'runtime' },
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
schemas.forEach(({ schema, name }) => {
|
|
110
|
+
const openAPISchema = z.toJSONSchema(schema, {
|
|
111
|
+
target: 'draft-7',
|
|
112
|
+
unrepresentable: 'any',
|
|
113
|
+
cycles: 'ref',
|
|
114
|
+
reused: 'ref',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const schemaWithMeta = {
|
|
118
|
+
title: name
|
|
119
|
+
.split('-')
|
|
120
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
121
|
+
.join(' '),
|
|
122
|
+
description: `OpenAPI schema for ${name}`,
|
|
123
|
+
...openAPISchema,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const outputPath = join(OUTPUT_SCHEMAS_DIR, `${name}.openapi.json`);
|
|
127
|
+
writeFileSync(outputPath, JSON.stringify(schemaWithMeta, null, 2) + '\n');
|
|
128
|
+
console.log(`Generated: ${outputPath}`);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Main execution
|
|
134
|
+
*/
|
|
135
|
+
function main(): void {
|
|
136
|
+
const includeOpenAPI = process.argv.includes('--openapi');
|
|
137
|
+
const watchMode = process.argv.includes('--watch');
|
|
138
|
+
|
|
139
|
+
if (watchMode) {
|
|
140
|
+
console.log('Watch mode not yet implemented');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
generateMainSchema();
|
|
145
|
+
generateIndividualSchemas();
|
|
146
|
+
|
|
147
|
+
if (includeOpenAPI) {
|
|
148
|
+
generateOpenAPISchemas();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
console.log('Schema generation complete');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
155
|
+
main();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { generateMainSchema, generateIndividualSchemas, generateOpenAPISchemas };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# JSON Schema Migration Summary: json-schema → json_schemer
|
|
2
|
+
|
|
3
|
+
## Migration Complete ✓
|
|
4
|
+
|
|
5
|
+
Successfully migrated from `json-schema` gem to `json_schemer` for better JSON Schema Draft 2020-12 support.
|
|
6
|
+
|
|
7
|
+
## Changes Made
|
|
8
|
+
|
|
9
|
+
### 1. Dependency Update
|
|
10
|
+
- **File**: `rhales.gemspec`
|
|
11
|
+
- **Change**: Replaced `json-schema ~> 4.0` with `json_schemer ~> 2.3`
|
|
12
|
+
- **Reason**: Better Draft 2020-12 support, modern API, superior performance
|
|
13
|
+
|
|
14
|
+
### 2. Middleware Implementation
|
|
15
|
+
- **File**: `lib/rhales/middleware/schema_validator.rb`
|
|
16
|
+
- **Changes**:
|
|
17
|
+
- Replaced `require 'json-schema'` with `require 'json_schemer'`
|
|
18
|
+
- Updated `load_schema_cached` to create JSONSchemer validator objects
|
|
19
|
+
- Removed `$schema` and `$id` stripping logic (json_schemer handles this natively)
|
|
20
|
+
- Replaced `JSON::Validator.fully_validate` with `schema.validate(data).to_a`
|
|
21
|
+
- Added `format_errors` method for human-readable error messages
|
|
22
|
+
- Maintained backward-compatible error message format
|
|
23
|
+
|
|
24
|
+
### 3. Test Updates
|
|
25
|
+
- **Files**:
|
|
26
|
+
- `spec/rhales/middleware/schema_validator_spec.rb`
|
|
27
|
+
- `spec/rhales/integration/schema_validation_spec.rb`
|
|
28
|
+
- **Changes**:
|
|
29
|
+
- Added `require 'fileutils'` where needed
|
|
30
|
+
- Added `require 'rack'` for Rack::Request
|
|
31
|
+
- All existing tests pass without modification to test logic
|
|
32
|
+
|
|
33
|
+
### 4. Documentation
|
|
34
|
+
- **File**: `CHANGELOG.md`
|
|
35
|
+
- **Added**: Entry documenting the migration and performance improvements
|
|
36
|
+
|
|
37
|
+
## Key Benefits
|
|
38
|
+
|
|
39
|
+
### 1. JSON Schema Draft 2020-12 Support
|
|
40
|
+
- Full support for latest schema standard
|
|
41
|
+
- Native handling of `$schema` and `$id` fields
|
|
42
|
+
- Better specification compliance
|
|
43
|
+
|
|
44
|
+
### 2. Performance Improvement
|
|
45
|
+
- **Before** (json-schema): ~2ms average validation time
|
|
46
|
+
- **After** (json_schemer): ~0.047ms average validation time
|
|
47
|
+
- **Improvement**: ~42x faster (98% reduction)
|
|
48
|
+
|
|
49
|
+
### 3. Better Error Messages
|
|
50
|
+
json_schemer provides structured error objects with:
|
|
51
|
+
- `data_pointer`: JSON Pointer to the invalid data
|
|
52
|
+
- `schema_pointer`: JSON Pointer to the schema rule
|
|
53
|
+
- `type`: Type of validation error
|
|
54
|
+
- `error`: Human-readable message
|
|
55
|
+
- Full error context for debugging
|
|
56
|
+
|
|
57
|
+
### 4. Modern API
|
|
58
|
+
```ruby
|
|
59
|
+
# Old (json-schema)
|
|
60
|
+
errors = JSON::Validator.fully_validate(schema, data, version: :draft4)
|
|
61
|
+
|
|
62
|
+
# New (json_schemer)
|
|
63
|
+
validator = JSONSchemer.schema(schema)
|
|
64
|
+
errors = validator.validate(data).to_a
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Error Message Examples
|
|
68
|
+
|
|
69
|
+
### Type Mismatch
|
|
70
|
+
```
|
|
71
|
+
The property '/authenticated' of type string did not match the following type: boolean
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Missing Required Field
|
|
75
|
+
```
|
|
76
|
+
The property '/' is missing required field(s): id, email
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Enum Validation
|
|
80
|
+
```
|
|
81
|
+
The property '/role' must be one of: admin, user, guest
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Range Validation
|
|
85
|
+
```
|
|
86
|
+
The property '/age' must be >= 0
|
|
87
|
+
The property '/age' must be <= 150
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Test Results
|
|
91
|
+
|
|
92
|
+
### All Tests Pass
|
|
93
|
+
```
|
|
94
|
+
533 examples, 0 failures
|
|
95
|
+
Finished in 0.30839 seconds
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Schema Validation Tests
|
|
99
|
+
```
|
|
100
|
+
26 examples, 0 failures
|
|
101
|
+
- 20 middleware unit tests
|
|
102
|
+
- 6 integration tests
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Performance Test
|
|
106
|
+
```
|
|
107
|
+
Average validation time: 0.0473 ms
|
|
108
|
+
Validated 10,000 times in 0.4726 seconds
|
|
109
|
+
Performance target: < 5ms ✓
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Compatibility
|
|
113
|
+
|
|
114
|
+
### Schema Format
|
|
115
|
+
No changes needed to existing schemas:
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
119
|
+
"$id": "https://rhales.dev/schemas/example.json",
|
|
120
|
+
"type": "object",
|
|
121
|
+
"properties": { ... }
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Middleware Configuration
|
|
126
|
+
No changes needed to middleware setup:
|
|
127
|
+
```ruby
|
|
128
|
+
use Rhales::Middleware::SchemaValidator,
|
|
129
|
+
schemas_dir: './public/schemas',
|
|
130
|
+
fail_on_error: ENV['RACK_ENV'] == 'development'
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Error Handling
|
|
134
|
+
Backward-compatible error message format maintained for existing error checks in tests and applications.
|
|
135
|
+
|
|
136
|
+
## Files Modified
|
|
137
|
+
|
|
138
|
+
1. `/Users/d/Projects/opensource/onetime/rhales/rhales.gemspec`
|
|
139
|
+
2. `/Users/d/Projects/opensource/onetime/rhales/lib/rhales/middleware/schema_validator.rb`
|
|
140
|
+
3. `/Users/d/Projects/opensource/onetime/rhales/spec/rhales/middleware/schema_validator_spec.rb`
|
|
141
|
+
4. `/Users/d/Projects/opensource/onetime/rhales/spec/rhales/integration/schema_validation_spec.rb`
|
|
142
|
+
5. `/Users/d/Projects/opensource/onetime/rhales/CHANGELOG.md`
|
|
143
|
+
|
|
144
|
+
## Acceptance Criteria - All Met ✓
|
|
145
|
+
|
|
146
|
+
- [x] `json_schemer` added to gemspec
|
|
147
|
+
- [x] `json-schema` removed from gemspec
|
|
148
|
+
- [x] Middleware updated to use json_schemer
|
|
149
|
+
- [x] Error formatting updated for better messages
|
|
150
|
+
- [x] All middleware tests passing (20/20)
|
|
151
|
+
- [x] All integration tests passing (6/6)
|
|
152
|
+
- [x] Demo schemas validate correctly
|
|
153
|
+
- [x] Full test suite passes (533/533 examples)
|
|
154
|
+
- [x] Performance maintained (< 0.05ms, well under 5ms target)
|
|
155
|
+
- [x] CHANGELOG updated
|
|
156
|
+
- [x] Backward-compatible error messages
|
|
157
|
+
|
|
158
|
+
## Next Steps
|
|
159
|
+
|
|
160
|
+
1. Deploy to staging environment
|
|
161
|
+
2. Monitor validation performance metrics
|
|
162
|
+
3. Consider leveraging json_schemer's additional features:
|
|
163
|
+
- Remote schema references ($ref to URLs)
|
|
164
|
+
- Custom format validators
|
|
165
|
+
- OpenAPI schema support
|
|
166
|
+
- Meta-schema validation
|
|
167
|
+
|
|
168
|
+
## References
|
|
169
|
+
|
|
170
|
+
- json_schemer: https://github.com/davishmcclurg/json_schemer
|
|
171
|
+
- JSON Schema Draft 2020-12: https://json-schema.org/draft/2020-12/schema
|
|
172
|
+
- Migration commit: feature/29-contract branch
|
data/lib/rhales/configuration.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# lib/rhales/configuration.rb
|
|
2
|
+
#
|
|
3
|
+
# frozen_string_literal: true
|
|
2
4
|
|
|
3
5
|
module Rhales
|
|
4
6
|
# Hydration-specific configuration settings
|
|
@@ -143,6 +145,18 @@ module Rhales
|
|
|
143
145
|
# Hydration settings
|
|
144
146
|
attr_accessor :hydration
|
|
145
147
|
|
|
148
|
+
# Schema validation settings
|
|
149
|
+
attr_accessor :enable_schema_validation, :fail_on_validation_error, :schemas_dir
|
|
150
|
+
|
|
151
|
+
# JSON response settings
|
|
152
|
+
attr_accessor :enable_json_responder, :json_responder_include_metadata
|
|
153
|
+
|
|
154
|
+
# Logging settings
|
|
155
|
+
attr_accessor :allowed_unescaped_variables
|
|
156
|
+
|
|
157
|
+
# Hydration mismatch reporting settings
|
|
158
|
+
attr_accessor :hydration_mismatch_format, :hydration_authority
|
|
159
|
+
|
|
146
160
|
def initialize
|
|
147
161
|
# Set sensible defaults
|
|
148
162
|
@default_locale = 'en'
|
|
@@ -160,6 +174,25 @@ module Rhales
|
|
|
160
174
|
@cache_parsed_templates = true
|
|
161
175
|
@cache_ttl = 3600 # 1 hour
|
|
162
176
|
@hydration = HydrationConfiguration.new
|
|
177
|
+
|
|
178
|
+
# Schema validation defaults
|
|
179
|
+
@enable_schema_validation = true
|
|
180
|
+
@fail_on_validation_error = false # Set by environment in middleware
|
|
181
|
+
@schemas_dir = './public/schemas' # Default to implementing project's public directory
|
|
182
|
+
|
|
183
|
+
# JSON responder defaults
|
|
184
|
+
@enable_json_responder = true
|
|
185
|
+
@json_responder_include_metadata = false
|
|
186
|
+
|
|
187
|
+
# Logging defaults
|
|
188
|
+
@allowed_unescaped_variables = []
|
|
189
|
+
|
|
190
|
+
# Hydration mismatch reporting defaults
|
|
191
|
+
@hydration_mismatch_format = :compact # :compact, :multiline, :sidebyside, :json
|
|
192
|
+
@hydration_authority = :schema # :schema or :data
|
|
193
|
+
|
|
194
|
+
# Yield to block for configuration if provided
|
|
195
|
+
yield(self) if block_given?
|
|
163
196
|
end
|
|
164
197
|
|
|
165
198
|
# Build API base URL from site configuration
|
|
@@ -253,6 +286,20 @@ module Rhales
|
|
|
253
286
|
yield(configuration) if block_given?
|
|
254
287
|
configuration.validate!
|
|
255
288
|
configuration.freeze!
|
|
289
|
+
|
|
290
|
+
# Debug log the configuration (guard against stale test mocks)
|
|
291
|
+
if Rhales.logger
|
|
292
|
+
require_relative 'utils/logging_helpers'
|
|
293
|
+
extend Rhales::Utils::LoggingHelpers
|
|
294
|
+
|
|
295
|
+
log_with_metadata(Rhales.logger, :debug, 'Rhales configured',
|
|
296
|
+
hydration_mismatch_format: configuration.hydration_mismatch_format,
|
|
297
|
+
hydration_authority: configuration.hydration_authority,
|
|
298
|
+
enable_schema_validation: configuration.enable_schema_validation,
|
|
299
|
+
fail_on_validation_error: configuration.fail_on_validation_error
|
|
300
|
+
)
|
|
301
|
+
end
|
|
302
|
+
|
|
256
303
|
configuration
|
|
257
304
|
end
|
|
258
305
|
|