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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/renovate.json5 +52 -0
  3. data/.github/workflows/ci.yml +123 -0
  4. data/.github/workflows/claude-code-review.yml +69 -0
  5. data/.github/workflows/claude.yml +49 -0
  6. data/.github/workflows/code-smells.yml +146 -0
  7. data/.github/workflows/ruby-lint.yml +78 -0
  8. data/.github/workflows/yardoc.yml +126 -0
  9. data/.gitignore +55 -0
  10. data/.pr_agent.toml +63 -0
  11. data/.pre-commit-config.yaml +89 -0
  12. data/.prettierignore +8 -0
  13. data/.prettierrc +38 -0
  14. data/.reek.yml +98 -0
  15. data/.rubocop.yml +428 -0
  16. data/.serena/.gitignore +3 -0
  17. data/.yardopts +56 -0
  18. data/CHANGELOG.md +44 -0
  19. data/CLAUDE.md +1 -1
  20. data/Gemfile +29 -0
  21. data/Gemfile.lock +189 -0
  22. data/README.md +686 -868
  23. data/Rakefile +46 -0
  24. data/debug_context.rb +25 -0
  25. data/demo/rhales-roda-demo/.gitignore +7 -0
  26. data/demo/rhales-roda-demo/Gemfile +32 -0
  27. data/demo/rhales-roda-demo/Gemfile.lock +151 -0
  28. data/demo/rhales-roda-demo/MAIL.md +405 -0
  29. data/demo/rhales-roda-demo/README.md +376 -0
  30. data/demo/rhales-roda-demo/RODA-TEMPLATE-ENGINES.md +192 -0
  31. data/demo/rhales-roda-demo/Rakefile +49 -0
  32. data/demo/rhales-roda-demo/app.rb +325 -0
  33. data/demo/rhales-roda-demo/bin/rackup +26 -0
  34. data/demo/rhales-roda-demo/config.ru +13 -0
  35. data/demo/rhales-roda-demo/db/migrate/001_create_rodauth_tables.rb +266 -0
  36. data/demo/rhales-roda-demo/db/migrate/002_create_rodauth_password_tables.rb +79 -0
  37. data/demo/rhales-roda-demo/db/migrate/003_add_admin_account.rb +68 -0
  38. data/demo/rhales-roda-demo/templates/change_login.rue +31 -0
  39. data/demo/rhales-roda-demo/templates/change_password.rue +36 -0
  40. data/demo/rhales-roda-demo/templates/close_account.rue +31 -0
  41. data/demo/rhales-roda-demo/templates/create_account.rue +40 -0
  42. data/demo/rhales-roda-demo/templates/dashboard.rue +150 -0
  43. data/demo/rhales-roda-demo/templates/home.rue +78 -0
  44. data/demo/rhales-roda-demo/templates/layouts/main.rue +168 -0
  45. data/demo/rhales-roda-demo/templates/login.rue +65 -0
  46. data/demo/rhales-roda-demo/templates/logout.rue +25 -0
  47. data/demo/rhales-roda-demo/templates/reset_password.rue +26 -0
  48. data/demo/rhales-roda-demo/templates/verify_account.rue +27 -0
  49. data/demo/rhales-roda-demo/test_full_output.rb +27 -0
  50. data/demo/rhales-roda-demo/test_simple.rb +24 -0
  51. data/docs/.gitignore +9 -0
  52. data/docs/architecture/data-flow.md +499 -0
  53. data/examples/dashboard-with-charts.rue +271 -0
  54. data/examples/form-with-validation.rue +180 -0
  55. data/examples/simple-page.rue +61 -0
  56. data/examples/vue.rue +136 -0
  57. data/generate-json-schemas.ts +158 -0
  58. data/json_schemer_migration_summary.md +172 -0
  59. data/lib/rhales/adapters/base_auth.rb +2 -0
  60. data/lib/rhales/adapters/base_request.rb +2 -0
  61. data/lib/rhales/adapters/base_session.rb +2 -0
  62. data/lib/rhales/adapters.rb +7 -0
  63. data/lib/rhales/configuration.rb +47 -0
  64. data/lib/rhales/core/context.rb +354 -0
  65. data/lib/rhales/{rue_document.rb → core/rue_document.rb} +56 -38
  66. data/lib/rhales/{template_engine.rb → core/template_engine.rb} +66 -59
  67. data/lib/rhales/{view.rb → core/view.rb} +112 -135
  68. data/lib/rhales/{view_composition.rb → core/view_composition.rb} +78 -8
  69. data/lib/rhales/core.rb +9 -0
  70. data/lib/rhales/errors/hydration_collision_error.rb +2 -0
  71. data/lib/rhales/errors.rb +2 -0
  72. data/lib/rhales/{earliest_injection_detector.rb → hydration/earliest_injection_detector.rb} +4 -0
  73. data/lib/rhales/hydration/hydration_data_aggregator.rb +487 -0
  74. data/lib/rhales/{hydration_endpoint.rb → hydration/hydration_endpoint.rb} +16 -12
  75. data/lib/rhales/{hydration_injector.rb → hydration/hydration_injector.rb} +4 -0
  76. data/lib/rhales/{hydration_registry.rb → hydration/hydration_registry.rb} +2 -0
  77. data/lib/rhales/hydration/hydrator.rb +102 -0
  78. data/lib/rhales/{link_based_injection_detector.rb → hydration/link_based_injection_detector.rb} +4 -0
  79. data/lib/rhales/{mount_point_detector.rb → hydration/mount_point_detector.rb} +4 -0
  80. data/lib/rhales/{safe_injection_validator.rb → hydration/safe_injection_validator.rb} +4 -0
  81. data/lib/rhales/hydration.rb +13 -0
  82. data/lib/rhales/{refinements → integrations/refinements}/require_refinements.rb +3 -1
  83. data/lib/rhales/{tilt.rb → integrations/tilt.rb} +22 -15
  84. data/lib/rhales/integrations.rb +6 -0
  85. data/lib/rhales/middleware/json_responder.rb +191 -0
  86. data/lib/rhales/middleware/schema_validator.rb +300 -0
  87. data/lib/rhales/middleware.rb +6 -0
  88. data/lib/rhales/parsers/handlebars_parser.rb +2 -0
  89. data/lib/rhales/parsers/rue_format_parser.rb +9 -7
  90. data/lib/rhales/parsers.rb +9 -0
  91. data/lib/rhales/{csp.rb → security/csp.rb} +27 -3
  92. data/lib/rhales/utils/json_serializer.rb +114 -0
  93. data/lib/rhales/utils/logging_helpers.rb +75 -0
  94. data/lib/rhales/utils/schema_extractor.rb +132 -0
  95. data/lib/rhales/utils/schema_generator.rb +194 -0
  96. data/lib/rhales/utils.rb +40 -0
  97. data/lib/rhales/version.rb +3 -1
  98. data/lib/rhales.rb +41 -24
  99. data/lib/tasks/rhales_schema.rake +197 -0
  100. data/package.json +10 -0
  101. data/pnpm-lock.yaml +345 -0
  102. data/pnpm-workspace.yaml +2 -0
  103. data/proofs/error_handling.rb +79 -0
  104. data/proofs/expanded_object_inheritance.rb +82 -0
  105. data/proofs/partial_context_scoping_fix.rb +168 -0
  106. data/proofs/ui_context_partial_inheritance.rb +236 -0
  107. data/rhales.gemspec +14 -6
  108. data/schema_vs_data_comparison.md +254 -0
  109. data/test_direct_access.rb +36 -0
  110. metadata +141 -23
  111. data/CLAUDE.locale.txt +0 -7
  112. data/lib/rhales/context.rb +0 -239
  113. data/lib/rhales/hydration_data_aggregator.rb +0 -221
  114. data/lib/rhales/hydrator.rb +0 -141
  115. data/lib/rhales/parsers/handlebars-grammar-review.txt +0 -39
data/.rubocop.yml ADDED
@@ -0,0 +1,428 @@
1
+ # .rubocop.yml
2
+ #
3
+ # This is the RuboCop configuration file.
4
+ # It contains the rules and settings for the RuboCop linter.
5
+ #
6
+ # Enable/disable the cops individually. For more information,
7
+ # refer to the RuboCop documentation:
8
+ # https://docs.rubocop.org/rubocop/cops.html
9
+
10
+ plugins:
11
+ - rubocop-thread_safety
12
+ - rubocop-performance
13
+ - rubocop-rspec
14
+
15
+ AllCops:
16
+ NewCops: enable
17
+ DisabledByDefault: false # flip to true for a good autocorrect time
18
+ UseCache: true
19
+ MaxFilesInCache: 1000
20
+ TargetRubyVersion: 3.4
21
+ Exclude:
22
+ - 'bin/bundle'
23
+ - 'node_modules/**/*'
24
+ - 'tmp/**/*'
25
+ - 'vendor/**/*'
26
+
27
+ RSpec/MultipleExpectations:
28
+ Enabled: true
29
+ Max: 5
30
+
31
+ RSpec/ExampleLength:
32
+ Enabled: true
33
+ Max: 10
34
+
35
+ Layout/CaseIndentation:
36
+ Enabled: true
37
+ EnforcedStyle: end # case, end
38
+ IndentOneStep: false
39
+ IndentationWidth: 2
40
+
41
+ Layout/CommentIndentation:
42
+ Enabled: true
43
+
44
+ Layout/MultilineMethodCallBraceLayout:
45
+ Enabled: true
46
+ EnforcedStyle: new_line # symmetrical, new_line, same_line
47
+
48
+ Layout/TrailingWhitespace:
49
+ Enabled: true
50
+
51
+ Layout/SpaceAroundEqualsInParameterDefault:
52
+ Enabled: true
53
+
54
+ Layout/SpaceAroundOperators:
55
+ Enabled: false
56
+
57
+ # Use parentheses around a logical expression if it makes easier to read.
58
+ Style/RedundantParentheses:
59
+ Enabled: false
60
+
61
+ Lint/UnusedMethodArgument:
62
+ Enabled: true
63
+
64
+ Lint/UselessAssignment:
65
+ Enabled: true
66
+
67
+ Lint/DuplicateBranch:
68
+ Enabled: true
69
+ IgnoreLiteralBranches: false
70
+ IgnoreConstantBranches: false
71
+ IgnoreDuplicateElseBranch: false
72
+
73
+ # Offense count: 3
74
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
75
+ Metrics/PerceivedComplexity:
76
+ Max: 20
77
+
78
+ # Offense count: 186
79
+ # Configuration parameters: AllowedConstants.
80
+ Style/Documentation:
81
+ Enabled: false
82
+
83
+ Style/RescueStandardError:
84
+ Enabled: true
85
+ EnforcedStyle: explicit
86
+
87
+ # When true: Use match? instead of =~ when MatchData is not used. True is preferred but not for autocorrection. Regexs are too picky. Need to manually check every time.
88
+ Performance/RegexpMatch:
89
+ Enabled: false
90
+
91
+ Style/TrailingCommaInHashLiteral:
92
+ Enabled: true
93
+ EnforcedStyleForMultiline: comma
94
+
95
+ Style/StringLiterals:
96
+ Enabled: true
97
+ EnforcedStyle: single_quotes
98
+
99
+ # The Style/DoubleNegation cop is disabled because double negation provides
100
+ # a concise, idiomatic way to convert values to boolean in Ruby. Alternative
101
+ # approaches like ternary expressions or comparison with nil create unnecessary
102
+ # verbosity without adding clarity. In cases where boolean coercion is the
103
+ # explicit intent, !! clearly communicates this purpose to other Ruby developers.
104
+ Style/DoubleNegation:
105
+ Enabled: false
106
+
107
+ # Offense count: non-0
108
+ Style/FormatString:
109
+ EnforcedStyle: format
110
+ Enabled: true
111
+
112
+ Style/FormatStringToken:
113
+ EnforcedStyle: unannotated
114
+ Enabled: true
115
+
116
+ Style/RedundantReturn:
117
+ Enabled: true
118
+ AllowMultipleReturnValues: false
119
+
120
+ Style/IfUnlessModifier:
121
+ Enabled: false
122
+
123
+ # We prefer `extend self` and `class << self`.
124
+ Style/ModuleFunction:
125
+ Enabled: true
126
+ AutoCorrect: false
127
+ EnforcedStyle: extend_self
128
+
129
+ Style/SymbolArray:
130
+ EnforcedStyle: brackets
131
+ Enabled: true
132
+
133
+ Style/StringLiteralsInInterpolation:
134
+ Enabled: true
135
+
136
+ Style/BlockDelimiters:
137
+ Enabled: true
138
+
139
+ Naming/PredicateMethod:
140
+ Enabled: true
141
+ Mode: 'conservative'
142
+ AllowedMethods:
143
+ - validate!
144
+ - migrate
145
+
146
+ # We use class instance variables quite a bit, mostly for readonly values set
147
+ # at boot time. Except for our models with have redis-rb Redis instances
148
+ # connected on their associated db via ModelClass.redis. We're well aware
149
+ # so keeping this disabled reduces warning noise.
150
+ ThreadSafety/ClassInstanceVariable:
151
+ Enabled: false
152
+
153
+ Naming/RescuedExceptionsVariableName:
154
+ Enabled: true
155
+ PreferredName: ex # Default is 'e'
156
+
157
+ Naming/PredicatePrefix:
158
+ Enabled: true
159
+ ForbiddenPrefixes: [is_, has_, have_]
160
+ AllowedMethods: [
161
+ has_passphrase?, # correlates with the REST API field `has_passphrase`
162
+ ]
163
+
164
+ Layout/MultilineMethodCallIndentation:
165
+ EnforcedStyle: indented
166
+ IndentationWidth: 2
167
+
168
+ Gemspec/DeprecatedAttributeAssignment:
169
+ Enabled: true
170
+
171
+ Gemspec/DevelopmentDependencies:
172
+ Enabled: true
173
+
174
+ Layout/ElseAlignment:
175
+ Enabled: false
176
+
177
+ Layout/EndAlignment:
178
+ Enabled: false
179
+ # Severity: low
180
+ # SupportedStylesAlignWith: 2
181
+ # Leave commented out. When we set align with, endless "error occurred"
182
+ # EnforcedStyle: keyword # keyword, variable, start_of_line
183
+
184
+ ## vvvvvv Causing ruby-lsp errors in zed ? (July 8)
185
+ ##
186
+ # Prefer 3 line if/else over one-liner
187
+ Style/GuardClause:
188
+ Enabled: false
189
+ MinBodyLength: 3
190
+ AllowConsecutiveConditionals: false
191
+
192
+ Layout/ExtraSpacing:
193
+ Enabled: false
194
+ AllowForAlignment: true
195
+ AllowBeforeTrailingComments: true
196
+ ForceEqualSignAlignment: true
197
+ ## ^^^^^^
198
+
199
+
200
+ Layout/IndentationConsistency:
201
+ EnforcedStyle: indented_internal_methods
202
+ Enabled: true
203
+
204
+ Layout/IndentationWidth:
205
+ # We don't want to enforce indentation width because it's doing weird things
206
+ # with if/else statements that capture values. The `if` expression is aligned
207
+ # with the right side of the `test` but the `else` expression is aligned with
208
+ # the start of the line.
209
+ Width: 2
210
+ Enabled: false
211
+
212
+ Layout/HashAlignment:
213
+ Enabled: true
214
+
215
+ Layout/FirstHashElementIndentation:
216
+ Enabled: true
217
+
218
+ Lint/Void:
219
+ Enabled: true
220
+
221
+ Lint/CopDirectiveSyntax:
222
+ Enabled: true
223
+
224
+ # Offense count: 122
225
+ # Assignment Branch Condition size
226
+ Metrics/AbcSize:
227
+ Enabled: false
228
+ Max: 20
229
+
230
+ # Offense count: 217
231
+ Layout/LineLength:
232
+ Enabled: false
233
+ AllowHeredoc: true
234
+ AllowURI: true
235
+ URISchemes:
236
+ - https
237
+ IgnoreCopDirectives: true
238
+ AllowedPatterns: []
239
+ SplitStrings: false
240
+ Max: 100
241
+
242
+ # Align the arguments of a method call if they span more than one line.
243
+ Layout/ArgumentAlignment:
244
+ Enabled: true
245
+ EnforcedStyle: with_fixed_indentation # with_first_argument, with_fixed_indentation
246
+ IndentationWidth: 2
247
+
248
+ Layout/EmptyLineAfterGuardClause:
249
+ Enabled: true
250
+
251
+ Layout/EmptyLineBetweenDefs:
252
+ Enabled: true
253
+
254
+ Layout/EmptyLines:
255
+ Enabled: true
256
+
257
+ Layout/EmptyLinesAroundAccessModifier:
258
+ Enabled: true
259
+
260
+ Layout/EmptyLinesAroundAttributeAccessor:
261
+ Enabled: true
262
+
263
+ Layout/EmptyLinesAroundBlockBody:
264
+ Enabled: true
265
+
266
+ Layout/EmptyLinesAroundClassBody:
267
+ Enabled: true
268
+
269
+ Layout/EmptyLinesAroundExceptionHandlingKeywords:
270
+ Enabled: true
271
+
272
+ Layout/EmptyLinesAroundMethodBody:
273
+ Enabled: true
274
+
275
+ Layout/EmptyLinesAroundModuleBody:
276
+ Enabled: true
277
+
278
+ Metrics/ClassLength:
279
+ Enabled: true
280
+ Max: 350
281
+
282
+ # Offense count: non-0
283
+ Metrics/MethodLength:
284
+ Enabled: true
285
+ Max: 50
286
+ CountAsOne: ['method_call']
287
+
288
+ Metrics/ModuleLength:
289
+ Enabled: true
290
+ Max: 350
291
+ CountAsOne: ['method_call']
292
+
293
+ Performance/Size:
294
+ Enabled: true
295
+ Exclude: []
296
+
297
+ Naming/AsciiIdentifiers:
298
+ Enabled: true
299
+
300
+ Metrics/CyclomaticComplexity:
301
+ Enabled: false
302
+
303
+ Style/NegatedIfElseCondition:
304
+ Enabled: true
305
+
306
+ Style/TrailingCommaInArguments:
307
+ Enabled: true
308
+ EnforcedStyleForMultiline: comma
309
+
310
+ Style/TrailingCommaInArrayLiteral:
311
+ Enabled: true
312
+ EnforcedStyleForMultiline: comma
313
+
314
+ # Use #empty? when testing for objects of length 0.
315
+ Style/ZeroLengthPredicate:
316
+ Enabled: true
317
+ Safe: true
318
+
319
+ Style/MethodDefParentheses:
320
+ Enabled: true
321
+
322
+ Style/FrozenStringLiteralComment:
323
+ Enabled: true
324
+ EnforcedStyle: never
325
+
326
+ Style/SuperArguments:
327
+ Enabled: true
328
+
329
+ # Offense count: non-0
330
+ ThreadSafety/ClassAndModuleAttributes:
331
+ Description: Avoid mutating class and module attributes.
332
+ Enabled: true
333
+ ActiveSupportClassAttributeAllowed: false
334
+
335
+ ThreadSafety/DirChdir:
336
+ Description: Avoid using `Dir.chdir` due to its process-wide effect.
337
+ Enabled: true
338
+ AllowCallWithBlock: false
339
+
340
+ # Do not assign mutable objects to class instance variables.
341
+ ThreadSafety/MutableClassInstanceVariable:
342
+ Description:
343
+ Enabled: true
344
+ EnforcedStyle: literals # one of literals, strict
345
+ SafeAutoCorrect: false
346
+
347
+ # Avoid starting new threads. Let a framework like Sidekiq handle the threads.
348
+ ThreadSafety/NewThread:
349
+ Enabled: true
350
+
351
+ # Avoid instance variables in Rack middleware.
352
+ ThreadSafety/RackMiddlewareInstanceVariable:
353
+ Description:
354
+ Enabled: true
355
+ Include:
356
+ - lib/middleware/*.rb
357
+
358
+ # Unsafe autocorrect:
359
+ Performance/MapCompact:
360
+ Enabled: false
361
+ Performance/StringInclude:
362
+ Enabled: false
363
+ Style/ClassAndModuleChildren:
364
+ Enabled: false
365
+ Style/GlobalStdStream:
366
+ Enabled: false
367
+ Style/HashConversion:
368
+ Enabled: false
369
+ Style/HashEachMethods:
370
+ Enabled: false
371
+ Style/IdenticalConditionalBranches:
372
+ Enabled: false
373
+ Style/MinMaxComparison:
374
+ Enabled: false
375
+ Style/MutableConstant:
376
+ Enabled: false
377
+ Style/NumericPredicate:
378
+ Enabled: false
379
+ Style/RaiseArgs:
380
+ Enabled: false
381
+ Style/RedundantInterpolation:
382
+ Enabled: false
383
+ Style/SafeNavigation:
384
+ Enabled: false
385
+ Style/SpecialGlobalVars:
386
+ Enabled: false
387
+ Style/StringConcatenation:
388
+ Enabled: false
389
+ Style/SymbolProc:
390
+ Enabled: false
391
+
392
+ # warnings
393
+ Lint/RedundantCopDisableDirective:
394
+ Enabled: false
395
+ Lint/AssignmentInCondition:
396
+ Enabled: false
397
+
398
+ # Manual corrections
399
+ Metrics/BlockLength:
400
+ Enabled: false
401
+ Metrics/BlockNesting:
402
+ Enabled: false
403
+ Metrics/ParameterLists:
404
+ Enabled: false
405
+ Naming/AccessorMethodName:
406
+ Enabled: false
407
+ Naming/MethodParameterName:
408
+ Enabled: false
409
+ Performance/CollectionLiteralInLoop:
410
+ Enabled: false
411
+ Style/OptionalBooleanParameter:
412
+ Enabled: false
413
+
414
+ # warnings
415
+ Lint/DuplicateMethods:
416
+ Enabled: false
417
+ Lint/UselessOr:
418
+ Enabled: false
419
+ Lint/UnreachableLoop:
420
+ Enabled: false
421
+ Lint/MissingCopEnableDirective:
422
+ Enabled: false
423
+ Lint/MissingSuper:
424
+ Enabled: false
425
+ Lint/EmptyFile:
426
+ Enabled: false
427
+ Lint/RescueException:
428
+ Enabled: false
@@ -0,0 +1,3 @@
1
+ *
2
+ !.gitignore
3
+ /cache
data/.yardopts ADDED
@@ -0,0 +1,56 @@
1
+ # YARD Documentation Configuration
2
+ # Systematic parameter specification for comprehensive API documentation generation
3
+
4
+ # Access level configuration: Include protected and private methods for complete API coverage
5
+ --protected
6
+ --private
7
+
8
+ # Markup processing configuration
9
+ --markup markdown
10
+ --markup-provider kramdown
11
+
12
+ # Output directory specification
13
+ --output-dir doc
14
+
15
+ # Primary documentation entry point
16
+ --readme README.md
17
+
18
+ # Supplementary documentation files
19
+ --files CHANGELOG.md,LICENSE.txt
20
+
21
+ # Path exclusion patterns: Remove non-library code from documentation scope
22
+ --exclude spec/**/*
23
+ --exclude demo/**/*
24
+ --exclude examples/**/*
25
+ --exclude apps/**/*
26
+ --exclude test/**/*
27
+ --exclude tmp/**/*
28
+
29
+ # Source file inclusion patterns: Target library implementation files
30
+ lib/**/*.rb
31
+
32
+ # Template specification for comprehensive documentation structure
33
+ --template default
34
+
35
+ # Additional processing directives
36
+ --verbose
37
+
38
+ # Documentation metadata
39
+ --title "Rhales - Server-rendered Components with Client-side Hydration"
40
+
41
+ # Tag processing configuration
42
+ --tag param:"Parameters"
43
+ --tag option:"Options"
44
+ --tag return:"Returns"
45
+ --tag raise:"Raises"
46
+ --tag example:"Example Usage"
47
+ --tag since:"Since"
48
+ --tag todo:"TODO"
49
+ --tag deprecated:"Deprecated"
50
+ --tag api:"API"
51
+ --tag internal:"Internal Use"
52
+
53
+ # Additional files for processing
54
+ -
55
+ README.md
56
+ CHANGELOG.md
data/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - **Production Logging**: Structured logging via `Rhales.logger=` for security auditing and debugging
12
+ - View rendering events with template details, timing, and hydration size
13
+ - Schema validation warnings for production debugging (missing/extra keys)
14
+ - Error logging with line numbers and section context
15
+ - Security events: unescaped variable warnings, CSP nonce generation
16
+ - Performance logging: template compilation, cache behavior, partial resolution
17
+ - Window collision detection prevents silent data overwrites when multiple templates use the same window attribute
18
+ - Explicit merge strategies (shallow, deep, strict) for controlled data sharing between templates
19
+ - `HydrationCollisionError` with detailed error messages showing file paths and line numbers
20
+ - `HydrationRegistry` for thread-safe tracking of window attributes per request
21
+ - `merge_strategy` method on RueDocument to extract merge attribute from data elements
22
+ - JavaScript merge functions for client-side data composition
23
+ - Comprehensive test coverage for collision detection and merge strategies
24
+
25
+ ### Changed
26
+ - Replaced `json-schema` gem with `json_schemer` for better JSON Schema Draft 2020-12 support
27
+ - Improved validation error messages with more structured output from json_schemer
28
+ - Validation performance improved to <0.05ms average (was ~2ms with json-schema)
29
+
30
+ ### Security
31
+ - Window collision detection prevents accidental data exposure by making overwrites explicit
32
+ - All merge operations happen client-side after server-side interpolation and JSON serialization
33
+ - Request-scoped registry prevents cross-request data leakage
34
+
35
+ ## [0.1.0] - 2024-01-XX
36
+
37
+ ### Added
38
+ - Initial release of Rhales
39
+ - Ruby Single File Components (.rue files) with server-side rendering
40
+ - Client-side data hydration with secure JSON injection
41
+ - Handlebars-style template syntax
42
+ - Pluggable authentication adapters
43
+ - Framework-agnostic design with Rails and Roda examples
44
+ - Comprehensive test suite
data/CLAUDE.md CHANGED
@@ -77,7 +77,7 @@ For complex features requiring parallel work:
77
77
 
78
78
  ### Key Patterns
79
79
  - **Template Syntax**: Uses Handlebars-style syntax (e.g., `{{variable}}`, `{{#if condition}}...{{/if}}`, `{{> partial_name}}`)
80
- - **Data Hydration**: Uses a `<data>` block in `.rue` files to define a JSON object for client-side hydration, which supports variable interpolation
80
+ - **Data Hydration**: Uses a `<schema>` block in `.rue` files to define a zod v4 schema in plain Javascript for client-side hydration
81
81
  - **Security**: Default HTML escaping, CSP nonce support for scripts, and CSRF token handling are built-in
82
82
  - **Configuration**: All configuration is handled via an injected `Configuration` object, avoiding global state
83
83
 
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rhales.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'benchmark'
8
+ gem 'rack-test'
9
+ gem 'reek', '~> 6.5'
10
+ gem 'rspec', '~> 3.12'
11
+ gem 'simplecov', '~> 0.22'
12
+ end
13
+
14
+ group :development do
15
+ gem 'benchmark-ips', '~> 2.0'
16
+ gem 'bundler', '~> 2.0'
17
+ gem 'debug'
18
+ gem 'kramdown', '~> 2.0' # Required for YARD markdown processing
19
+ gem 'rack', '>= 3.2', '< 4.0'
20
+ gem 'rack-proxy', require: false
21
+ gem 'rake', '~> 13.0'
22
+ gem 'rubocop', '1.81'
23
+ gem 'rubocop-performance', require: false
24
+ gem 'rubocop-rspec', require: false
25
+ gem 'rubocop-thread_safety', require: false
26
+ gem 'stackprof', require: false
27
+ gem 'syntax_tree', require: false
28
+ gem 'yard', '~> 0.9'
29
+ end