rapitapir 0.1.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 (157) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +57 -0
  4. data/CHANGELOG.md +94 -0
  5. data/CLEANUP_SUMMARY.md +155 -0
  6. data/CONTRIBUTING.md +280 -0
  7. data/LICENSE +21 -0
  8. data/README.md +485 -0
  9. data/debug_hash.rb +20 -0
  10. data/docs/EXTENSION_COMPARISON.md +388 -0
  11. data/docs/SINATRA_EXTENSION.md +467 -0
  12. data/docs/archive/PHASE_1_2_COMPLETE.md +77 -0
  13. data/docs/archive/PHASE_1_3_COMPLETE.md +152 -0
  14. data/docs/archive/PHASE_2_1_OBSERVABILITY_COMPLETED.md +203 -0
  15. data/docs/archive/PHASE_2_SUMMARY.md +209 -0
  16. data/docs/archive/REFACTORING_SUMMARY.md +184 -0
  17. data/docs/archive/phase_1_3_plan.md +136 -0
  18. data/docs/archive/sinatra_extension_summary.md +188 -0
  19. data/docs/archive/sinatra_working_solution.md +113 -0
  20. data/docs/archive/typescript-client-generator-summary.md +259 -0
  21. data/docs/auto-derivation.md +146 -0
  22. data/docs/blueprint.md +1091 -0
  23. data/docs/endpoint-definition.md +211 -0
  24. data/docs/github_pages_fix.md +52 -0
  25. data/docs/github_pages_setup.md +49 -0
  26. data/docs/implementation-status.md +357 -0
  27. data/docs/observability.md +647 -0
  28. data/docs/phase3-plan.md +108 -0
  29. data/docs/sinatra_rapitapir.md +87 -0
  30. data/docs/type_shortcuts.md +146 -0
  31. data/examples/README_ENTERPRISE.md +202 -0
  32. data/examples/authentication_example.rb +192 -0
  33. data/examples/auto_derivation_ruby_friendly.rb +163 -0
  34. data/examples/cli/user_api_endpoints.rb +56 -0
  35. data/examples/client/typescript_client_example.rb +102 -0
  36. data/examples/client/user-api-client.ts +193 -0
  37. data/examples/demo_api.rb +41 -0
  38. data/examples/docs/documentation_example.rb +112 -0
  39. data/examples/docs/user-api-docs.html +789 -0
  40. data/examples/docs/user-api-docs.md +403 -0
  41. data/examples/enhanced_auto_derivation_test.rb +83 -0
  42. data/examples/enterprise_extension_demo.rb +417 -0
  43. data/examples/enterprise_rapitapir_api.rb +662 -0
  44. data/examples/getting_started_extension.rb +218 -0
  45. data/examples/hello_world.rb +74 -0
  46. data/examples/oauth2/.env.example +19 -0
  47. data/examples/oauth2/README.md +205 -0
  48. data/examples/oauth2/generic_oauth2_api.rb +226 -0
  49. data/examples/oauth2/get_token.rb +72 -0
  50. data/examples/oauth2/songs_api_with_auth0.rb +320 -0
  51. data/examples/oauth2/test_api.sh +16 -0
  52. data/examples/oauth2/test_songs_api.sh +110 -0
  53. data/examples/observability/.env.example +35 -0
  54. data/examples/observability/README.md +230 -0
  55. data/examples/observability/README_HONEYCOMB.md +332 -0
  56. data/examples/observability/advanced_setup.rb +384 -0
  57. data/examples/observability/basic_setup.rb +192 -0
  58. data/examples/observability/complete_test.rb +121 -0
  59. data/examples/observability/honeycomb_example.rb +523 -0
  60. data/examples/observability/honeycomb_rapitapir_clean.rb +488 -0
  61. data/examples/observability/honeycomb_rapitapir_example.rb +523 -0
  62. data/examples/observability/honeycomb_working_example.rb +489 -0
  63. data/examples/observability/quick_test.rb +78 -0
  64. data/examples/observability/simple_test.rb +14 -0
  65. data/examples/observability/test_honeycomb_demo.rb +354 -0
  66. data/examples/observability/test_live_honeycomb.rb +111 -0
  67. data/examples/observability/test_validation.rb +78 -0
  68. data/examples/observability/test_working_validation.rb +66 -0
  69. data/examples/openapi/user_api_schema.rb +132 -0
  70. data/examples/production_ready_example.rb +105 -0
  71. data/examples/rails/users_controller.rb +146 -0
  72. data/examples/readme/basic_sinatra_example.rb +128 -0
  73. data/examples/server/user_api.rb +179 -0
  74. data/examples/simple_auto_derivation_demo.rb +44 -0
  75. data/examples/simple_demo_api.rb +18 -0
  76. data/examples/sinatra/user_app.rb +127 -0
  77. data/examples/t_shortcut_demo.rb +59 -0
  78. data/examples/user_api.rb +190 -0
  79. data/examples/working_getting_started.rb +184 -0
  80. data/examples/working_simple_example.rb +195 -0
  81. data/lib/rapitapir/auth/configuration.rb +129 -0
  82. data/lib/rapitapir/auth/context.rb +122 -0
  83. data/lib/rapitapir/auth/errors.rb +104 -0
  84. data/lib/rapitapir/auth/middleware.rb +324 -0
  85. data/lib/rapitapir/auth/oauth2.rb +350 -0
  86. data/lib/rapitapir/auth/schemes.rb +420 -0
  87. data/lib/rapitapir/auth.rb +113 -0
  88. data/lib/rapitapir/cli/command.rb +535 -0
  89. data/lib/rapitapir/cli/server.rb +243 -0
  90. data/lib/rapitapir/cli/validator.rb +373 -0
  91. data/lib/rapitapir/client/generator_base.rb +272 -0
  92. data/lib/rapitapir/client/typescript_generator.rb +350 -0
  93. data/lib/rapitapir/core/endpoint.rb +158 -0
  94. data/lib/rapitapir/core/enhanced_endpoint.rb +235 -0
  95. data/lib/rapitapir/core/input.rb +182 -0
  96. data/lib/rapitapir/core/output.rb +164 -0
  97. data/lib/rapitapir/core/request.rb +19 -0
  98. data/lib/rapitapir/core/response.rb +17 -0
  99. data/lib/rapitapir/docs/html_generator.rb +780 -0
  100. data/lib/rapitapir/docs/markdown_generator.rb +464 -0
  101. data/lib/rapitapir/dsl/endpoint_dsl.rb +116 -0
  102. data/lib/rapitapir/dsl/enhanced_endpoint_dsl.rb +62 -0
  103. data/lib/rapitapir/dsl/enhanced_input.rb +73 -0
  104. data/lib/rapitapir/dsl/enhanced_output.rb +63 -0
  105. data/lib/rapitapir/dsl/enhanced_structures.rb +393 -0
  106. data/lib/rapitapir/dsl/fluent_dsl.rb +72 -0
  107. data/lib/rapitapir/dsl/fluent_endpoint_builder.rb +316 -0
  108. data/lib/rapitapir/dsl/http_verbs.rb +77 -0
  109. data/lib/rapitapir/dsl/input_methods.rb +47 -0
  110. data/lib/rapitapir/dsl/observability_methods.rb +81 -0
  111. data/lib/rapitapir/dsl/output_methods.rb +43 -0
  112. data/lib/rapitapir/dsl/type_resolution.rb +43 -0
  113. data/lib/rapitapir/observability/configuration.rb +108 -0
  114. data/lib/rapitapir/observability/health_check.rb +236 -0
  115. data/lib/rapitapir/observability/logging.rb +270 -0
  116. data/lib/rapitapir/observability/metrics.rb +203 -0
  117. data/lib/rapitapir/observability/middleware.rb +243 -0
  118. data/lib/rapitapir/observability/tracing.rb +143 -0
  119. data/lib/rapitapir/observability.rb +28 -0
  120. data/lib/rapitapir/openapi/schema_generator.rb +403 -0
  121. data/lib/rapitapir/schema.rb +136 -0
  122. data/lib/rapitapir/server/enhanced_rack_adapter.rb +379 -0
  123. data/lib/rapitapir/server/middleware.rb +120 -0
  124. data/lib/rapitapir/server/path_matcher.rb +45 -0
  125. data/lib/rapitapir/server/rack_adapter.rb +215 -0
  126. data/lib/rapitapir/server/rails_adapter.rb +17 -0
  127. data/lib/rapitapir/server/rails_adapter_class.rb +53 -0
  128. data/lib/rapitapir/server/rails_controller.rb +72 -0
  129. data/lib/rapitapir/server/rails_input_processor.rb +73 -0
  130. data/lib/rapitapir/server/rails_response_handler.rb +29 -0
  131. data/lib/rapitapir/server/sinatra_adapter.rb +200 -0
  132. data/lib/rapitapir/server/sinatra_integration.rb +93 -0
  133. data/lib/rapitapir/sinatra/configuration.rb +91 -0
  134. data/lib/rapitapir/sinatra/extension.rb +214 -0
  135. data/lib/rapitapir/sinatra/oauth2_helpers.rb +236 -0
  136. data/lib/rapitapir/sinatra/resource_builder.rb +152 -0
  137. data/lib/rapitapir/sinatra/swagger_ui_generator.rb +166 -0
  138. data/lib/rapitapir/sinatra_rapitapir.rb +40 -0
  139. data/lib/rapitapir/types/array.rb +163 -0
  140. data/lib/rapitapir/types/auto_derivation.rb +265 -0
  141. data/lib/rapitapir/types/base.rb +146 -0
  142. data/lib/rapitapir/types/boolean.rb +46 -0
  143. data/lib/rapitapir/types/date.rb +92 -0
  144. data/lib/rapitapir/types/datetime.rb +98 -0
  145. data/lib/rapitapir/types/email.rb +32 -0
  146. data/lib/rapitapir/types/float.rb +134 -0
  147. data/lib/rapitapir/types/hash.rb +161 -0
  148. data/lib/rapitapir/types/integer.rb +143 -0
  149. data/lib/rapitapir/types/object.rb +156 -0
  150. data/lib/rapitapir/types/optional.rb +65 -0
  151. data/lib/rapitapir/types/string.rb +185 -0
  152. data/lib/rapitapir/types/uuid.rb +32 -0
  153. data/lib/rapitapir/types.rb +155 -0
  154. data/lib/rapitapir/version.rb +5 -0
  155. data/lib/rapitapir.rb +173 -0
  156. data/rapitapir.gemspec +66 -0
  157. metadata +387 -0
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module RapiTapir
6
+ module Core
7
+ # Output format definition for HTTP endpoints
8
+ #
9
+ # Represents different types of response outputs that an endpoint can produce,
10
+ # including JSON responses, XML responses, status codes, and headers.
11
+ #
12
+ # @example JSON response
13
+ # RapiTapir::Core::Output.new(kind: :json, type: user_schema)
14
+ #
15
+ # @example Status response
16
+ # RapiTapir::Core::Output.new(kind: :status, type: 404)
17
+ class Output
18
+ VALID_KINDS = %i[json xml status header].freeze
19
+
20
+ attr_reader :kind, :type, :options
21
+
22
+ def initialize(kind:, type:, options: {})
23
+ @kind = kind
24
+ @type = type
25
+ validate_kind!(kind)
26
+ validate_type!(type)
27
+ @options = options.freeze
28
+ end
29
+
30
+ def valid_type?(value)
31
+ case type
32
+ when :string then value.is_a?(String)
33
+ when :integer then integer_type?(value)
34
+ when :float then float_type?(value)
35
+ when :boolean then boolean_type?(value)
36
+ when Hash then validate_hash_schema(value)
37
+ when Class then value.is_a?(type)
38
+ else true # Accept any for custom types and status codes
39
+ end
40
+ end
41
+
42
+ def integer_type?(value)
43
+ value.is_a?(Integer) || value.is_a?(Float)
44
+ end
45
+
46
+ def float_type?(value)
47
+ value.is_a?(Float) || value.is_a?(Integer)
48
+ end
49
+
50
+ def serialize(value)
51
+ case kind
52
+ when :json then serialize_json(value)
53
+ when :xml then serialize_xml(value)
54
+ when :status then value.to_i
55
+ when :header then value.to_s
56
+ else value
57
+ end
58
+ end
59
+
60
+ def to_h
61
+ {
62
+ kind: kind,
63
+ type: type,
64
+ options: options
65
+ }
66
+ end
67
+
68
+ private
69
+
70
+ def validate_kind!(kind)
71
+ return if VALID_KINDS.include?(kind)
72
+
73
+ raise ArgumentError, "Invalid kind: #{kind}. Must be one of #{VALID_KINDS}"
74
+ end
75
+
76
+ def validate_type!(type)
77
+ case kind
78
+ when :status
79
+ validate_status_type!(type)
80
+ when :json, :xml
81
+ # Allow any type for JSON/XML bodies
82
+ when :header
83
+ validate_header_type!(type)
84
+ end
85
+ end
86
+
87
+ def validate_status_type!(type)
88
+ return if type.is_a?(Integer) && type >= 100 && type <= 599
89
+
90
+ raise ArgumentError, "Status type must be an integer between 100-599, got: #{type}"
91
+ end
92
+
93
+ def validate_header_type!(type)
94
+ return if [:string, String].include?(type) || type.is_a?(Class)
95
+
96
+ raise ArgumentError, "Header type must be :string or a Class, got: #{type}"
97
+ end
98
+
99
+ def validate_hash_schema(value)
100
+ return false unless value.is_a?(Hash)
101
+ return true unless type.is_a?(Hash) # If type is not a hash schema, accept any hash
102
+
103
+ type.all? do |key, expected_type|
104
+ valid_field_type?(value[key], expected_type)
105
+ end
106
+ end
107
+
108
+ def valid_field_type?(field_value, expected_type)
109
+ case expected_type
110
+ when :string then field_value.is_a?(String)
111
+ when :integer then field_value.is_a?(Integer)
112
+ when :float then numeric_type?(field_value)
113
+ when :boolean then boolean_type?(field_value)
114
+ when :date then date_type?(field_value)
115
+ when :datetime then datetime_type?(field_value)
116
+ else true
117
+ end
118
+ end
119
+
120
+ def numeric_type?(field_value)
121
+ field_value.is_a?(Float) || field_value.is_a?(Integer)
122
+ end
123
+
124
+ def boolean_type?(field_value)
125
+ [true, false].include?(field_value)
126
+ end
127
+
128
+ def date_type?(field_value)
129
+ field_value.is_a?(Date) || field_value.is_a?(String)
130
+ end
131
+
132
+ def datetime_type?(field_value)
133
+ field_value.is_a?(DateTime) || field_value.is_a?(String)
134
+ end
135
+
136
+ def serialize_json(value)
137
+ case value
138
+ when String then value
139
+ else JSON.generate(value)
140
+ end
141
+ rescue JSON::GeneratorError, JSON::NestingError => e
142
+ raise TypeError, "Cannot serialize value to JSON: #{e.message}"
143
+ end
144
+
145
+ def serialize_xml(value)
146
+ # Basic XML serialization - would need a proper XML library in practice
147
+ case value
148
+ when String then value
149
+ when Hash then hash_to_xml(value)
150
+ else value.to_s
151
+ end
152
+ end
153
+
154
+ def hash_to_xml(hash, root = 'root')
155
+ xml = "<#{root}>"
156
+ hash.each do |key, value|
157
+ xml += "<#{key}>#{value}</#{key}>"
158
+ end
159
+ xml += "</#{root}>"
160
+ xml
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RapiTapir
4
+ module Core
5
+ # HTTP request wrapper for RapiTapir endpoints
6
+ # Provides a standardized interface for HTTP request data
7
+ class Request
8
+ attr_reader :method, :path, :headers, :params, :body
9
+
10
+ def initialize(method:, path:, headers: {}, params: {}, body: nil)
11
+ @method = method
12
+ @path = path
13
+ @headers = headers.freeze
14
+ @params = params.freeze
15
+ @body = body
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RapiTapir
4
+ module Core
5
+ # HTTP response wrapper for RapiTapir endpoints
6
+ # Provides a standardized interface for HTTP response data
7
+ class Response
8
+ attr_reader :status, :headers, :body
9
+
10
+ def initialize(status:, headers: {}, body: nil)
11
+ @status = status
12
+ @headers = headers.freeze
13
+ @body = body
14
+ end
15
+ end
16
+ end
17
+ end