rhales 0.3.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 -2
- data/Gemfile +29 -0
- data/Gemfile.lock +189 -0
- data/README.md +706 -589
- 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 +161 -1
- data/lib/rhales/core/context.rb +354 -0
- data/lib/rhales/{rue_document.rb → core/rue_document.rb} +59 -43
- data/lib/rhales/{template_engine.rb → core/template_engine.rb} +80 -33
- data/lib/rhales/core/view.rb +529 -0
- data/lib/rhales/{view_composition.rb → core/view_composition.rb} +81 -9
- 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/hydration/earliest_injection_detector.rb +153 -0
- data/lib/rhales/hydration/hydration_data_aggregator.rb +487 -0
- data/lib/rhales/hydration/hydration_endpoint.rb +215 -0
- data/lib/rhales/hydration/hydration_injector.rb +175 -0
- data/lib/rhales/{hydration_registry.rb → hydration/hydration_registry.rb} +2 -0
- data/lib/rhales/hydration/hydrator.rb +102 -0
- data/lib/rhales/hydration/link_based_injection_detector.rb +195 -0
- data/lib/rhales/hydration/mount_point_detector.rb +109 -0
- data/lib/rhales/hydration/safe_injection_validator.rb +103 -0
- data/lib/rhales/hydration.rb +13 -0
- data/lib/rhales/{refinements → integrations/refinements}/require_refinements.rb +7 -13
- data/lib/rhales/{tilt.rb → integrations/tilt.rb} +26 -18
- 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 +55 -36
- 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 +5 -1
- data/lib/rhales.rb +47 -19
- 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 +142 -18
- data/CLAUDE.locale.txt +0 -7
- data/lib/rhales/context.rb +0 -240
- data/lib/rhales/hydration_data_aggregator.rb +0 -220
- data/lib/rhales/hydrator.rb +0 -141
- data/lib/rhales/parsers/handlebars-grammar-review.txt +0 -39
- data/lib/rhales/view.rb +0 -412
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Schema vs Data Section Comparison for Onetime Secret Migration
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
✅ **Schema sections are ready for Onetime Secret migration**
|
|
6
|
+
|
|
7
|
+
The test demonstrates that `<schema>` sections provide **direct JSON serialization** without template interpolation, which is exactly what's needed for Vue SPA mount points.
|
|
8
|
+
|
|
9
|
+
## Key Findings
|
|
10
|
+
|
|
11
|
+
### 1. Data Flow with Schema Sections
|
|
12
|
+
|
|
13
|
+
**Backend (Ruby):**
|
|
14
|
+
```ruby
|
|
15
|
+
view.render('vue_spa_mount',
|
|
16
|
+
ui: { theme: 'dark', locale: 'en' },
|
|
17
|
+
authentication: { authenticated: true, custid: 'cust_12345' },
|
|
18
|
+
user: { email: 'test@example.com', account_since: 1640000000 },
|
|
19
|
+
# ... more props
|
|
20
|
+
)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Template (.rue file):**
|
|
24
|
+
```xml
|
|
25
|
+
<schema lang="js-zod" window="__ONETIME_STATE__">
|
|
26
|
+
const schema = z.object({
|
|
27
|
+
ui: z.object({
|
|
28
|
+
theme: z.string(),
|
|
29
|
+
locale: z.string()
|
|
30
|
+
}),
|
|
31
|
+
authentication: z.object({
|
|
32
|
+
authenticated: z.boolean(),
|
|
33
|
+
custid: z.string().nullable()
|
|
34
|
+
}),
|
|
35
|
+
# ... more schema definitions
|
|
36
|
+
});
|
|
37
|
+
</schema>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<!DOCTYPE html>
|
|
41
|
+
<html>
|
|
42
|
+
<body>
|
|
43
|
+
<div id="app"><router-view></router-view></div>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
</template>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Rendered Output:**
|
|
50
|
+
```html
|
|
51
|
+
<script id="rsfc-data-..." type="application/json" data-window="__ONETIME_STATE__">
|
|
52
|
+
{"ui":{"theme":"dark","locale":"en"},"authentication":{"authenticated":true,"custid":"cust_12345"},"user":{"email":"test@example.com","account_since":1640000000},...}
|
|
53
|
+
</script>
|
|
54
|
+
<script nonce="..." data-hydration-target="__ONETIME_STATE__">
|
|
55
|
+
window['__ONETIME_STATE__'] = JSON.parse(dataScript.textContent);
|
|
56
|
+
</script>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. Critical Differences: Schema vs Data Sections
|
|
60
|
+
|
|
61
|
+
| Feature | Data Section (deprecated) | Schema Section (current) |
|
|
62
|
+
|---------|--------------------------|-------------------------|
|
|
63
|
+
| **Backend Props** | Can pass any values, uses interpolation | Must pass fully-resolved values |
|
|
64
|
+
| **Template Syntax** | `{"user": "{{user.name}}"}` | Props serialized directly |
|
|
65
|
+
| **Interpolation** | Yes - `{{var}}` evaluated | No - props → JSON directly |
|
|
66
|
+
| **Type Safety** | No | Yes (via Zod schema) |
|
|
67
|
+
| **JSON Output** | After interpolation | Direct serialization |
|
|
68
|
+
|
|
69
|
+
### 3. What This Means for Onetime Secret
|
|
70
|
+
|
|
71
|
+
**Current System (data section):**
|
|
72
|
+
```ruby
|
|
73
|
+
# VuePoint passes pre-serialized JSON
|
|
74
|
+
locals = {
|
|
75
|
+
'ui' => UiSerializer.serialize(...).to_json, # ❌ Already JSON string
|
|
76
|
+
'authentication' => {...}.to_json # ❌ Already JSON string
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```xml
|
|
81
|
+
<data window="__ONETIME_STATE__">
|
|
82
|
+
{
|
|
83
|
+
"ui": {{{ui}}}, # ❌ Triple braces for raw output
|
|
84
|
+
"authentication": {{{authentication}}}
|
|
85
|
+
}
|
|
86
|
+
</data>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**New System (schema section):**
|
|
90
|
+
```ruby
|
|
91
|
+
# VuePoint passes Ruby hashes
|
|
92
|
+
locals = {
|
|
93
|
+
'ui' => UiSerializer.serialize(...), # ✅ Just the hash
|
|
94
|
+
'authentication' => {...} # ✅ Just the hash
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```xml
|
|
99
|
+
<schema lang="js-zod" window="__ONETIME_STATE__">
|
|
100
|
+
const schema = z.object({
|
|
101
|
+
ui: z.object({ theme: z.string(), locale: z.string() }),
|
|
102
|
+
authentication: z.object({ authenticated: z.boolean(), custid: z.string().nullable() })
|
|
103
|
+
});
|
|
104
|
+
</schema>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4. Implementation Code Path
|
|
108
|
+
|
|
109
|
+
From `lib/rhales/hydration_data_aggregator.rb:50-90`:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
def process_schema_section(parser)
|
|
113
|
+
window_attr = parser.schema_window || 'data'
|
|
114
|
+
|
|
115
|
+
# CRITICAL: Direct serialization of props (no template interpolation)
|
|
116
|
+
processed_data = @context.props
|
|
117
|
+
|
|
118
|
+
# ... merge logic ...
|
|
119
|
+
|
|
120
|
+
@merged_data[window_attr] = processed_data
|
|
121
|
+
end
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The key insight: **Schema sections skip the template interpolation step entirely** and serialize `@context.props` directly to JSON.
|
|
125
|
+
|
|
126
|
+
### 5. Tested Scenarios
|
|
127
|
+
|
|
128
|
+
✅ Complex nested objects (ui, authentication, user, etc.)
|
|
129
|
+
✅ Nil/null values (nullable schema fields)
|
|
130
|
+
✅ Boolean values (true/false preserved)
|
|
131
|
+
✅ Numbers (integers preserved)
|
|
132
|
+
✅ Strings with template-like syntax (not interpolated)
|
|
133
|
+
✅ Custom window attribute (`__ONETIME_STATE__`)
|
|
134
|
+
✅ CSP nonce integration (`{{app.nonce}}` in template)
|
|
135
|
+
✅ Dark mode inline script (before hydration)
|
|
136
|
+
✅ Vue SPA mount point (`<div id="app">`)
|
|
137
|
+
|
|
138
|
+
### 6. Migration Checklist for Onetime Secret
|
|
139
|
+
|
|
140
|
+
- [ ] Remove `.to_json` calls in VuePoint class
|
|
141
|
+
- [ ] Pass Ruby hashes as locals (not JSON strings)
|
|
142
|
+
- [ ] Convert `<data>` section to `<schema>` section
|
|
143
|
+
- [ ] Remove triple-braces `{{{var}}}` (not needed with schema)
|
|
144
|
+
- [ ] Define Zod schema matching serializer structure
|
|
145
|
+
- [ ] Test with all 6 serializers (Config, Auth, Domain, I18n, Messages, System)
|
|
146
|
+
- [ ] Verify `window.__ONETIME_STATE__` structure is identical
|
|
147
|
+
- [ ] Verify Vue.js initializes correctly with new hydration
|
|
148
|
+
|
|
149
|
+
### 7. Benefits of Schema Sections
|
|
150
|
+
|
|
151
|
+
1. **Simpler Backend Code**: No need to pre-serialize to JSON
|
|
152
|
+
2. **Type Safety**: Zod schema catches mismatches at build time
|
|
153
|
+
3. **Validation**: Runtime validation with middleware (optional)
|
|
154
|
+
4. **Cleaner Templates**: No template interpolation confusion
|
|
155
|
+
5. **JSON Schema Generation**: Can generate TypeScript types
|
|
156
|
+
6. **Better Performance**: One serialization pass (not two)
|
|
157
|
+
|
|
158
|
+
## Example Migration
|
|
159
|
+
|
|
160
|
+
**Before (current Onetime Secret):**
|
|
161
|
+
```ruby
|
|
162
|
+
# apps/web/core/views.rb
|
|
163
|
+
class VuePoint < BaseView
|
|
164
|
+
def render(template_name)
|
|
165
|
+
@serialized_data = run_serializers(@view_vars, i18n)
|
|
166
|
+
|
|
167
|
+
locals = {}
|
|
168
|
+
@serialized_data.each do |key, value|
|
|
169
|
+
locals[key] = value.to_json # Pre-serialize everything
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
super(template_name, locals: locals)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```xml
|
|
178
|
+
<!-- index.html.erb -->
|
|
179
|
+
<data window="__ONETIME_STATE__">
|
|
180
|
+
{
|
|
181
|
+
"ui": {{{ui}}},
|
|
182
|
+
"authentication": {{{authentication}}},
|
|
183
|
+
"custid": "{{{custid}}}",
|
|
184
|
+
...
|
|
185
|
+
}
|
|
186
|
+
</data>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**After (with Rhales schema):**
|
|
190
|
+
```ruby
|
|
191
|
+
# apps/web/core/views.rb
|
|
192
|
+
class VuePoint
|
|
193
|
+
def render(template_name)
|
|
194
|
+
@serialized_data = run_serializers(@view_vars, i18n)
|
|
195
|
+
|
|
196
|
+
# Pass hashes directly - no .to_json needed
|
|
197
|
+
view = Rhales::View.new(@req)
|
|
198
|
+
view.render(template_name, @serialized_data)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```xml
|
|
204
|
+
<!-- index.rue -->
|
|
205
|
+
<schema lang="js-zod" window="__ONETIME_STATE__">
|
|
206
|
+
const schema = z.object({
|
|
207
|
+
ui: z.object({
|
|
208
|
+
theme: z.string(),
|
|
209
|
+
locale: z.string()
|
|
210
|
+
}),
|
|
211
|
+
authentication: z.object({
|
|
212
|
+
authenticated: z.boolean(),
|
|
213
|
+
custid: z.string().nullable()
|
|
214
|
+
}),
|
|
215
|
+
// ... define all 40+ fields from serializers
|
|
216
|
+
});
|
|
217
|
+
</schema>
|
|
218
|
+
|
|
219
|
+
<template>
|
|
220
|
+
<!DOCTYPE html>
|
|
221
|
+
<html lang="{{locale}}" class="light">
|
|
222
|
+
<head>
|
|
223
|
+
<script nonce="{{app.nonce}}" language="javascript" type="text/javascript">
|
|
224
|
+
// Dark mode script
|
|
225
|
+
</script>
|
|
226
|
+
</head>
|
|
227
|
+
<body>
|
|
228
|
+
<div id="app"><router-view></router-view></div>
|
|
229
|
+
</body>
|
|
230
|
+
</html>
|
|
231
|
+
</template>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Conclusion
|
|
235
|
+
|
|
236
|
+
Schema sections are **production-ready** for the Onetime Secret migration. The test demonstrates:
|
|
237
|
+
|
|
238
|
+
1. Direct JSON serialization without interpolation
|
|
239
|
+
2. Correct handling of complex nested structures
|
|
240
|
+
3. Proper nil/null value handling
|
|
241
|
+
4. CSP nonce integration
|
|
242
|
+
5. Custom window variables
|
|
243
|
+
6. Vue SPA mount point compatibility
|
|
244
|
+
|
|
245
|
+
The migration simplifies backend code by eliminating pre-serialization and provides type safety through Zod schemas.
|
|
246
|
+
|
|
247
|
+
## Next Steps
|
|
248
|
+
|
|
249
|
+
1. Create full Zod schema definition for all 40+ Onetime Secret fields
|
|
250
|
+
2. Refactor VuePoint to pass hashes instead of JSON strings
|
|
251
|
+
3. Convert index.html.erb to index.rue with schema section
|
|
252
|
+
4. Run integration tests to verify `window.__ONETIME_STATE__` structure
|
|
253
|
+
5. Test Vue.js initialization with new hydration format
|
|
254
|
+
6. Deploy to staging for validation
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Simple test to verify direct access works
|
|
4
|
+
require_relative 'lib/rhales'
|
|
5
|
+
|
|
6
|
+
# Create a test configuration
|
|
7
|
+
config = Rhales::Configuration.new do |conf|
|
|
8
|
+
conf.template_paths = [File.join(__dir__, 'spec/fixtures/templates')]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Create a view with test props
|
|
12
|
+
view = Rhales::View.new(
|
|
13
|
+
nil, nil, nil, 'en',
|
|
14
|
+
client: { 'greeting' => 'Hello World', 'user' => { 'name' => 'John Doe' } },
|
|
15
|
+
config: config
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# Render the template
|
|
19
|
+
result = view.render('test_direct_access')
|
|
20
|
+
|
|
21
|
+
puts "=== Rendered Output ==="
|
|
22
|
+
puts result
|
|
23
|
+
puts "======================="
|
|
24
|
+
|
|
25
|
+
# Check if direct access worked
|
|
26
|
+
if result.include?('Direct: Hello World')
|
|
27
|
+
puts "✅ Direct access to 'message' works"
|
|
28
|
+
else
|
|
29
|
+
puts "❌ Direct access to 'message' failed"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if result.include?('User: John Doe')
|
|
33
|
+
puts "✅ Direct access to 'userName' works"
|
|
34
|
+
else
|
|
35
|
+
puts "❌ Direct access to 'userName' failed"
|
|
36
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,56 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rhales
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- delano
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
-
dependencies:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: json_schemer
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.3'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.3'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: logger
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: tilt
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2'
|
|
12
54
|
description: |
|
|
13
55
|
Rhales is a framework for building server-rendered components with
|
|
14
56
|
client-side data hydration using .rue files called RSFCs (Ruby
|
|
@@ -23,33 +65,115 @@ executables: []
|
|
|
23
65
|
extensions: []
|
|
24
66
|
extra_rdoc_files: []
|
|
25
67
|
files:
|
|
26
|
-
-
|
|
68
|
+
- ".github/renovate.json5"
|
|
69
|
+
- ".github/workflows/ci.yml"
|
|
70
|
+
- ".github/workflows/claude-code-review.yml"
|
|
71
|
+
- ".github/workflows/claude.yml"
|
|
72
|
+
- ".github/workflows/code-smells.yml"
|
|
73
|
+
- ".github/workflows/ruby-lint.yml"
|
|
74
|
+
- ".github/workflows/yardoc.yml"
|
|
75
|
+
- ".gitignore"
|
|
76
|
+
- ".pr_agent.toml"
|
|
77
|
+
- ".pre-commit-config.yaml"
|
|
78
|
+
- ".prettierignore"
|
|
79
|
+
- ".prettierrc"
|
|
80
|
+
- ".reek.yml"
|
|
81
|
+
- ".rubocop.yml"
|
|
82
|
+
- ".serena/.gitignore"
|
|
83
|
+
- ".yardopts"
|
|
84
|
+
- CHANGELOG.md
|
|
27
85
|
- CLAUDE.md
|
|
86
|
+
- Gemfile
|
|
87
|
+
- Gemfile.lock
|
|
28
88
|
- LICENSE.txt
|
|
29
89
|
- README.md
|
|
90
|
+
- Rakefile
|
|
91
|
+
- debug_context.rb
|
|
92
|
+
- demo/rhales-roda-demo/.gitignore
|
|
93
|
+
- demo/rhales-roda-demo/Gemfile
|
|
94
|
+
- demo/rhales-roda-demo/Gemfile.lock
|
|
95
|
+
- demo/rhales-roda-demo/MAIL.md
|
|
96
|
+
- demo/rhales-roda-demo/README.md
|
|
97
|
+
- demo/rhales-roda-demo/RODA-TEMPLATE-ENGINES.md
|
|
98
|
+
- demo/rhales-roda-demo/Rakefile
|
|
99
|
+
- demo/rhales-roda-demo/app.rb
|
|
100
|
+
- demo/rhales-roda-demo/bin/rackup
|
|
101
|
+
- demo/rhales-roda-demo/config.ru
|
|
102
|
+
- demo/rhales-roda-demo/db/migrate/001_create_rodauth_tables.rb
|
|
103
|
+
- demo/rhales-roda-demo/db/migrate/002_create_rodauth_password_tables.rb
|
|
104
|
+
- demo/rhales-roda-demo/db/migrate/003_add_admin_account.rb
|
|
105
|
+
- demo/rhales-roda-demo/templates/change_login.rue
|
|
106
|
+
- demo/rhales-roda-demo/templates/change_password.rue
|
|
107
|
+
- demo/rhales-roda-demo/templates/close_account.rue
|
|
108
|
+
- demo/rhales-roda-demo/templates/create_account.rue
|
|
109
|
+
- demo/rhales-roda-demo/templates/dashboard.rue
|
|
110
|
+
- demo/rhales-roda-demo/templates/home.rue
|
|
111
|
+
- demo/rhales-roda-demo/templates/layouts/main.rue
|
|
112
|
+
- demo/rhales-roda-demo/templates/login.rue
|
|
113
|
+
- demo/rhales-roda-demo/templates/logout.rue
|
|
114
|
+
- demo/rhales-roda-demo/templates/reset_password.rue
|
|
115
|
+
- demo/rhales-roda-demo/templates/verify_account.rue
|
|
116
|
+
- demo/rhales-roda-demo/test_full_output.rb
|
|
117
|
+
- demo/rhales-roda-demo/test_simple.rb
|
|
118
|
+
- docs/.gitignore
|
|
119
|
+
- docs/architecture/data-flow.md
|
|
120
|
+
- examples/dashboard-with-charts.rue
|
|
121
|
+
- examples/form-with-validation.rue
|
|
122
|
+
- examples/simple-page.rue
|
|
123
|
+
- examples/vue.rue
|
|
124
|
+
- generate-json-schemas.ts
|
|
125
|
+
- json_schemer_migration_summary.md
|
|
30
126
|
- lib/rhales.rb
|
|
127
|
+
- lib/rhales/adapters.rb
|
|
31
128
|
- lib/rhales/adapters/base_auth.rb
|
|
32
129
|
- lib/rhales/adapters/base_request.rb
|
|
33
130
|
- lib/rhales/adapters/base_session.rb
|
|
34
131
|
- lib/rhales/configuration.rb
|
|
35
|
-
- lib/rhales/
|
|
36
|
-
- lib/rhales/
|
|
132
|
+
- lib/rhales/core.rb
|
|
133
|
+
- lib/rhales/core/context.rb
|
|
134
|
+
- lib/rhales/core/rue_document.rb
|
|
135
|
+
- lib/rhales/core/template_engine.rb
|
|
136
|
+
- lib/rhales/core/view.rb
|
|
137
|
+
- lib/rhales/core/view_composition.rb
|
|
37
138
|
- lib/rhales/errors.rb
|
|
38
139
|
- lib/rhales/errors/hydration_collision_error.rb
|
|
39
|
-
- lib/rhales/
|
|
40
|
-
- lib/rhales/
|
|
41
|
-
- lib/rhales/
|
|
42
|
-
- lib/rhales/
|
|
140
|
+
- lib/rhales/hydration.rb
|
|
141
|
+
- lib/rhales/hydration/earliest_injection_detector.rb
|
|
142
|
+
- lib/rhales/hydration/hydration_data_aggregator.rb
|
|
143
|
+
- lib/rhales/hydration/hydration_endpoint.rb
|
|
144
|
+
- lib/rhales/hydration/hydration_injector.rb
|
|
145
|
+
- lib/rhales/hydration/hydration_registry.rb
|
|
146
|
+
- lib/rhales/hydration/hydrator.rb
|
|
147
|
+
- lib/rhales/hydration/link_based_injection_detector.rb
|
|
148
|
+
- lib/rhales/hydration/mount_point_detector.rb
|
|
149
|
+
- lib/rhales/hydration/safe_injection_validator.rb
|
|
150
|
+
- lib/rhales/integrations.rb
|
|
151
|
+
- lib/rhales/integrations/refinements/require_refinements.rb
|
|
152
|
+
- lib/rhales/integrations/tilt.rb
|
|
153
|
+
- lib/rhales/middleware.rb
|
|
154
|
+
- lib/rhales/middleware/json_responder.rb
|
|
155
|
+
- lib/rhales/middleware/schema_validator.rb
|
|
156
|
+
- lib/rhales/parsers.rb
|
|
43
157
|
- lib/rhales/parsers/handlebars_parser.rb
|
|
44
158
|
- lib/rhales/parsers/rue_format_parser.rb
|
|
45
|
-
- lib/rhales/
|
|
46
|
-
- lib/rhales/
|
|
47
|
-
- lib/rhales/
|
|
48
|
-
- lib/rhales/
|
|
159
|
+
- lib/rhales/security/csp.rb
|
|
160
|
+
- lib/rhales/utils.rb
|
|
161
|
+
- lib/rhales/utils/json_serializer.rb
|
|
162
|
+
- lib/rhales/utils/logging_helpers.rb
|
|
163
|
+
- lib/rhales/utils/schema_extractor.rb
|
|
164
|
+
- lib/rhales/utils/schema_generator.rb
|
|
49
165
|
- lib/rhales/version.rb
|
|
50
|
-
- lib/
|
|
51
|
-
-
|
|
166
|
+
- lib/tasks/rhales_schema.rake
|
|
167
|
+
- package.json
|
|
168
|
+
- pnpm-lock.yaml
|
|
169
|
+
- pnpm-workspace.yaml
|
|
170
|
+
- proofs/error_handling.rb
|
|
171
|
+
- proofs/expanded_object_inheritance.rb
|
|
172
|
+
- proofs/partial_context_scoping_fix.rb
|
|
173
|
+
- proofs/ui_context_partial_inheritance.rb
|
|
52
174
|
- rhales.gemspec
|
|
175
|
+
- schema_vs_data_comparison.md
|
|
176
|
+
- test_direct_access.rb
|
|
53
177
|
homepage: https://github.com/onetimesecret/rhales
|
|
54
178
|
licenses:
|
|
55
179
|
- MIT
|
|
@@ -65,14 +189,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
65
189
|
requirements:
|
|
66
190
|
- - ">="
|
|
67
191
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 3.4
|
|
192
|
+
version: 3.3.4
|
|
69
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
194
|
requirements:
|
|
71
195
|
- - ">="
|
|
72
196
|
- !ruby/object:Gem::Version
|
|
73
197
|
version: '0'
|
|
74
198
|
requirements: []
|
|
75
|
-
rubygems_version: 3.
|
|
199
|
+
rubygems_version: 3.7.2
|
|
76
200
|
specification_version: 4
|
|
77
201
|
summary: Rhales - Server-rendered components with client-side hydration (RSFCs)
|
|
78
202
|
test_files: []
|
data/CLAUDE.locale.txt
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
Our own private local claude notes. Not read by claude or checked in.
|
|
2
|
-
|
|
3
|
-
https://claudelog.com/mechanics/plan-mode
|
|
4
|
-
https://handlebars-lang.github.io/spec/#sec-handlebars-specification-statements
|
|
5
|
-
https://github.com/jeremyevans/rodauth/tree/588b865cf70c7f327f0f24a4e277dfe787a6674f/doc
|
|
6
|
-
https://docs.anthropic.com/en/docs/claude-code/hooks#subagentstop
|
|
7
|
-
https://www.anthropic.com/engineering/claude-code-best-practices
|