iron_admin 0.4.1 → 0.6.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 (456) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +66 -30
  3. data/app/assets/config/iron_admin_manifest.js +12 -0
  4. data/app/components/iron_admin/dashboards/metric_card_component.html.haml +8 -3
  5. data/app/components/iron_admin/dashboards/metric_card_component.rb +21 -1
  6. data/app/components/iron_admin/form/belongs_to_component.rb +60 -6
  7. data/app/components/iron_admin/form/nested_form_component.html.haml +28 -0
  8. data/app/components/iron_admin/form/nested_form_component.rb +81 -0
  9. data/app/components/iron_admin/resources/data_table_component.html.haml +1 -1
  10. data/app/components/iron_admin/resources/data_table_component.rb +6 -0
  11. data/app/components/iron_admin/resources/show_field_component.rb +2 -0
  12. data/app/controllers/iron_admin/application_controller.rb +32 -1
  13. data/app/controllers/iron_admin/concerns/action_executable.rb +44 -0
  14. data/app/controllers/iron_admin/concerns/filterable.rb +84 -0
  15. data/app/controllers/iron_admin/concerns/json_params_coercion.rb +67 -0
  16. data/app/controllers/iron_admin/concerns/nested_permittable.rb +36 -0
  17. data/app/controllers/iron_admin/concerns/scopeable.rb +84 -0
  18. data/app/controllers/iron_admin/concerns/searchable.rb +13 -16
  19. data/app/controllers/iron_admin/exports_controller.rb +15 -11
  20. data/app/controllers/iron_admin/imports_controller.rb +83 -0
  21. data/app/controllers/iron_admin/live_controller.rb +12 -0
  22. data/app/controllers/iron_admin/resources_controller.rb +118 -117
  23. data/app/controllers/iron_admin/search_controller.rb +5 -5
  24. data/app/controllers/iron_admin/tools_controller.rb +63 -4
  25. data/app/helpers/iron_admin/application_helper.rb +33 -14
  26. data/app/helpers/iron_admin/field_display_helper.rb +160 -1
  27. data/app/javascript/iron_admin/controllers/cp_nested_form_controller.js +113 -0
  28. data/app/javascript/iron_admin/controllers/filter_operator_controller.js +10 -0
  29. data/app/javascript/iron_admin/index.js +4 -0
  30. data/app/views/iron_admin/dashboard/index.html.haml +7 -2
  31. data/app/views/iron_admin/form/_nested_row.html.haml +70 -0
  32. data/app/views/iron_admin/imports/new.html.haml +27 -0
  33. data/app/views/iron_admin/imports/preview.html.haml +31 -0
  34. data/app/views/iron_admin/resources/_form.html.haml +81 -5
  35. data/app/views/iron_admin/resources/action_form.html.haml +62 -0
  36. data/app/views/iron_admin/resources/bulk_action_form.html.haml +62 -0
  37. data/app/views/iron_admin/resources/index.html.haml +60 -18
  38. data/app/views/iron_admin/tools/action_form.html.haml +57 -0
  39. data/app/views/iron_admin/tools/show.html.haml +20 -1
  40. data/config/importmap.rb +2 -0
  41. data/config/locales/en.yml +36 -0
  42. data/config/routes.rb +7 -0
  43. data/docs/components/filter-components.md +60 -0
  44. data/docs/getting-started/installation.md +113 -27
  45. data/docs/getting-started/quick-start.md +17 -1
  46. data/docs/guides/authentication.md +7 -6
  47. data/docs/guides/custom-adapters.md +628 -0
  48. data/docs/guides/extending.md +132 -3
  49. data/docs/guides/fields.md +1 -1
  50. data/docs/guides/resources.md +78 -2
  51. data/docs/guides/troubleshooting.md +68 -10
  52. data/docs/reference/routes.md +10 -0
  53. data/lib/generators/iron_admin/install/install_generator.rb +49 -4
  54. data/lib/generators/iron_admin/install/templates/dashboard.rb.tt +5 -1
  55. data/lib/generators/iron_admin/install_audit/install_audit_generator.rb +26 -10
  56. data/lib/generators/iron_admin/resource/resource_generator.rb +1 -1
  57. data/lib/generators/iron_admin/resource/templates/resource.rb.tt +6 -2
  58. data/lib/iron_admin/action_field.rb +56 -0
  59. data/lib/iron_admin/adapters/active_record.rb +237 -0
  60. data/lib/iron_admin/adapters/base.rb +340 -0
  61. data/lib/iron_admin/adapters/http/column_descriptor.rb +10 -0
  62. data/lib/iron_admin/adapters/http/configuration.rb +27 -0
  63. data/lib/iron_admin/adapters/http/connection.rb +117 -0
  64. data/lib/iron_admin/adapters/http/model_proxy.rb +75 -0
  65. data/lib/iron_admin/adapters/http/query.rb +111 -0
  66. data/lib/iron_admin/adapters/http/record.rb +83 -0
  67. data/lib/iron_admin/adapters/http/type_inferrer.rb +51 -0
  68. data/lib/iron_admin/adapters/http.rb +241 -0
  69. data/lib/iron_admin/adapters/mongoid/association_wrapper.rb +74 -0
  70. data/lib/iron_admin/adapters/mongoid/column_descriptor.rb +10 -0
  71. data/lib/iron_admin/adapters/mongoid.rb +284 -0
  72. data/lib/iron_admin/adapters/registry.rb +44 -0
  73. data/lib/iron_admin/concerns/importable.rb +81 -0
  74. data/lib/iron_admin/concerns/live_updatable.rb +38 -0
  75. data/lib/iron_admin/concerns/nestable.rb +69 -0
  76. data/lib/iron_admin/concerns/soft_deletable.rb +61 -0
  77. data/lib/iron_admin/configuration.rb +20 -0
  78. data/lib/iron_admin/dashboard.rb +15 -20
  79. data/lib/iron_admin/engine.rb +35 -22
  80. data/lib/iron_admin/errors.rb +29 -0
  81. data/lib/iron_admin/field_inferrer.rb +61 -22
  82. data/lib/iron_admin/filters/active_record_query_builder.rb +63 -0
  83. data/lib/iron_admin/filters/base_query_builder.rb +55 -0
  84. data/lib/iron_admin/filters/http_query_builder.rb +39 -0
  85. data/lib/iron_admin/filters/mongoid_query_builder.rb +58 -0
  86. data/lib/iron_admin/filters/query_builder.rb +12 -0
  87. data/lib/iron_admin/import/column_mapper.rb +42 -0
  88. data/lib/iron_admin/import/import_preview.rb +10 -0
  89. data/lib/iron_admin/import/import_result.rb +10 -0
  90. data/lib/iron_admin/import/importer.rb +231 -0
  91. data/lib/iron_admin/import/parser/csv.rb +34 -0
  92. data/lib/iron_admin/import/parser/json.rb +36 -0
  93. data/lib/iron_admin/import/type_caster.rb +47 -0
  94. data/lib/iron_admin/live/broadcaster.rb +43 -0
  95. data/lib/iron_admin/live/poll_cache.rb +28 -0
  96. data/lib/iron_admin/live.rb +29 -0
  97. data/lib/iron_admin/nested_association.rb +15 -0
  98. data/lib/iron_admin/nested_attributes_validator.rb +25 -0
  99. data/lib/iron_admin/policy.rb +72 -13
  100. data/lib/iron_admin/resource.rb +149 -91
  101. data/lib/iron_admin/resource_registry.rb +77 -4
  102. data/lib/iron_admin/tool.rb +50 -0
  103. data/lib/iron_admin/tool_action.rb +73 -0
  104. data/lib/iron_admin/tool_context.rb +49 -0
  105. data/lib/iron_admin/version.rb +1 -1
  106. data/lib/iron_admin.rb +46 -10
  107. data/vendor/bundle/ruby/3.2.0/cache/addressable-2.9.0.gem +0 -0
  108. data/vendor/bundle/ruby/3.2.0/cache/crack-1.0.1.gem +0 -0
  109. data/vendor/bundle/ruby/3.2.0/cache/faraday-2.14.1.gem +0 -0
  110. data/vendor/bundle/ruby/3.2.0/cache/faraday-net_http-3.4.2.gem +0 -0
  111. data/vendor/bundle/ruby/3.2.0/cache/hashdiff-1.2.1.gem +0 -0
  112. data/vendor/bundle/ruby/3.2.0/cache/net-http-0.9.1.gem +0 -0
  113. data/vendor/bundle/ruby/3.2.0/cache/public_suffix-7.0.5.gem +0 -0
  114. data/vendor/bundle/ruby/3.2.0/cache/rexml-3.4.4.gem +0 -0
  115. data/vendor/bundle/ruby/3.2.0/cache/webmock-3.26.2.gem +0 -0
  116. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/bigdecimal.so +0 -0
  117. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/gem_make.out +6 -6
  118. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/mkmf.log +25 -25
  119. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/date_core.so +0 -0
  120. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/gem_make.out +6 -6
  121. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/mkmf.log +4 -4
  122. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/erb/escape.so +0 -0
  123. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/gem_make.out +6 -6
  124. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/mkmf.log +2 -2
  125. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/gem_make.out +6 -6
  126. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/io/console.so +0 -0
  127. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/mkmf.log +22 -22
  128. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/gem_make.out +6 -6
  129. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/json/ext/generator.so +0 -0
  130. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/json/ext/parser.so +0 -0
  131. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/mkmf.log +9 -9
  132. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/gem_make.out +6 -6
  133. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/mkmf.log +12 -12
  134. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/nio4r_ext.so +0 -0
  135. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/gem_make.out +6 -6
  136. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/mkmf.log +6 -6
  137. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/prism/prism.so +0 -0
  138. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/gem_make.out +6 -6
  139. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/mkmf.log +7 -7
  140. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/psych.so +0 -0
  141. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/racc-1.8.1/gem_make.out +6 -6
  142. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/racc-1.8.1/racc/cparse.so +0 -0
  143. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/redcarpet-3.6.1/gem_make.out +6 -6
  144. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/redcarpet-3.6.1/redcarpet.so +0 -0
  145. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/gem_make.out +6 -6
  146. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/mkmf.log +2 -2
  147. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/stringio.so +0 -0
  148. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/websocket-driver-0.8.0/gem_make.out +6 -6
  149. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/websocket-driver-0.8.0/websocket_mask.so +0 -0
  150. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/CHANGELOG.md +326 -0
  151. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/LICENSE.txt +202 -0
  152. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/README.md +121 -0
  153. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna/native.rb +66 -0
  154. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna/pure.rb +4710 -0
  155. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna.rb +26 -0
  156. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/template.rb +1040 -0
  157. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/uri.rb +2602 -0
  158. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/version.rb +31 -0
  159. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable.rb +4 -0
  160. data/vendor/bundle/ruby/3.2.0/gems/bigdecimal-4.0.1/ext/bigdecimal/Makefile +3 -3
  161. data/vendor/bundle/ruby/3.2.0/gems/bigdecimal-4.0.1/lib/bigdecimal.so +0 -0
  162. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/History +58 -0
  163. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/LICENSE +20 -0
  164. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/README.md +43 -0
  165. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/json.rb +113 -0
  166. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/util.rb +17 -0
  167. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/version.rb +3 -0
  168. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/xml.rb +240 -0
  169. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack.rb +8 -0
  170. data/vendor/bundle/ruby/3.2.0/gems/date-3.5.1/ext/date/Makefile +3 -3
  171. data/vendor/bundle/ruby/3.2.0/gems/date-3.5.1/lib/date_core.so +0 -0
  172. data/vendor/bundle/ruby/3.2.0/gems/erb-6.0.1/ext/erb/escape/Makefile +3 -3
  173. data/vendor/bundle/ruby/3.2.0/gems/erb-6.0.1/lib/erb/escape.so +0 -0
  174. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/CHANGELOG.md +574 -0
  175. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/LICENSE.md +20 -0
  176. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/README.md +67 -0
  177. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/Rakefile +12 -0
  178. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/examples/client_spec.rb +119 -0
  179. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/examples/client_test.rb +144 -0
  180. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter/test.rb +311 -0
  181. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter.rb +101 -0
  182. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter_registry.rb +30 -0
  183. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/connection.rb +565 -0
  184. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  185. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  186. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/error.rb +202 -0
  187. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/logging/formatter.rb +118 -0
  188. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/methods.rb +6 -0
  189. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/middleware.rb +72 -0
  190. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/middleware_registry.rb +83 -0
  191. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/connection_options.rb +23 -0
  192. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/env.rb +204 -0
  193. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/proxy_options.rb +38 -0
  194. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/request_options.rb +23 -0
  195. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/ssl_options.rb +76 -0
  196. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options.rb +219 -0
  197. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/parameters.rb +5 -0
  198. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/rack_builder.rb +248 -0
  199. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/authorization.rb +54 -0
  200. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/instrumentation.rb +58 -0
  201. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/json.rb +70 -0
  202. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/url_encoded.rb +60 -0
  203. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request.rb +139 -0
  204. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/json.rb +74 -0
  205. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/logger.rb +39 -0
  206. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/raise_error.rb +83 -0
  207. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response.rb +95 -0
  208. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils/headers.rb +150 -0
  209. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils/params_hash.rb +61 -0
  210. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils.rb +121 -0
  211. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/version.rb +5 -0
  212. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday.rb +158 -0
  213. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/external_adapters/faraday_specs_setup.rb +14 -0
  214. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter/test_spec.rb +442 -0
  215. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter_registry_spec.rb +28 -0
  216. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter_spec.rb +55 -0
  217. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/connection_spec.rb +841 -0
  218. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/error_spec.rb +175 -0
  219. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/middleware_registry_spec.rb +31 -0
  220. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/middleware_spec.rb +213 -0
  221. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/env_spec.rb +76 -0
  222. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/options_spec.rb +297 -0
  223. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/proxy_options_spec.rb +79 -0
  224. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/request_options_spec.rb +19 -0
  225. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/params_encoders/flat_spec.rb +42 -0
  226. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/params_encoders/nested_spec.rb +151 -0
  227. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/rack_builder_spec.rb +317 -0
  228. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/authorization_spec.rb +118 -0
  229. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/instrumentation_spec.rb +74 -0
  230. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/json_spec.rb +199 -0
  231. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/url_encoded_spec.rb +93 -0
  232. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request_spec.rb +110 -0
  233. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/json_spec.rb +206 -0
  234. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/logger_spec.rb +299 -0
  235. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/raise_error_spec.rb +286 -0
  236. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response_spec.rb +84 -0
  237. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/utils/headers_spec.rb +109 -0
  238. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/utils_spec.rb +120 -0
  239. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday_spec.rb +43 -0
  240. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/spec_helper.rb +133 -0
  241. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/disabling_stub.rb +14 -0
  242. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/fake_safe_buffer.rb +15 -0
  243. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/faraday_middleware_subclasses.rb +18 -0
  244. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/helper_methods.rb +96 -0
  245. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/adapter.rb +105 -0
  246. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/params_encoder.rb +18 -0
  247. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/request_method.rb +263 -0
  248. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/streaming_response_checker.rb +35 -0
  249. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/LICENSE.md +21 -0
  250. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/README.md +57 -0
  251. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb +206 -0
  252. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/net_http/version.rb +7 -0
  253. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/net_http.rb +10 -0
  254. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/Gemfile +8 -0
  255. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/LICENSE +19 -0
  256. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/README.md +323 -0
  257. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/Rakefile +18 -0
  258. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/changelog.md +127 -0
  259. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/hashdiff.gemspec +39 -0
  260. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/compare_hashes.rb +101 -0
  261. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/diff.rb +185 -0
  262. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/lcs.rb +66 -0
  263. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/lcs_compare_arrays.rb +32 -0
  264. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/linear_compare_array.rb +159 -0
  265. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/patch.rb +88 -0
  266. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/util.rb +155 -0
  267. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/version.rb +5 -0
  268. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff.rb +10 -0
  269. data/vendor/bundle/ruby/3.2.0/gems/io-console-0.8.2/ext/io/console/Makefile +3 -3
  270. data/vendor/bundle/ruby/3.2.0/gems/io-console-0.8.2/lib/io/console.so +0 -0
  271. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/ext/json/ext/generator/Makefile +3 -3
  272. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/ext/json/ext/parser/Makefile +3 -3
  273. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/lib/json/ext/generator.so +0 -0
  274. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/lib/json/ext/parser.so +0 -0
  275. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/BSDL +22 -0
  276. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/COPYING +56 -0
  277. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/README.md +93 -0
  278. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/doc/net-http/examples.rdoc +31 -0
  279. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/doc/net-http/included_getters.rdoc +3 -0
  280. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/exceptions.rb +35 -0
  281. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/generic_request.rb +429 -0
  282. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/header.rb +985 -0
  283. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/proxy_delta.rb +17 -0
  284. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/request.rb +88 -0
  285. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/requests.rb +444 -0
  286. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/response.rb +739 -0
  287. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/responses.rb +1242 -0
  288. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/status.rb +84 -0
  289. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http.rb +2608 -0
  290. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/https.rb +23 -0
  291. data/vendor/bundle/ruby/3.2.0/gems/nio4r-2.7.5/ext/nio4r/Makefile +3 -3
  292. data/vendor/bundle/ruby/3.2.0/gems/nio4r-2.7.5/lib/nio4r_ext.so +0 -0
  293. data/vendor/bundle/ruby/3.2.0/gems/prism-1.9.0/ext/prism/Makefile +3 -3
  294. data/vendor/bundle/ruby/3.2.0/gems/prism-1.9.0/lib/prism/prism.so +0 -0
  295. data/vendor/bundle/ruby/3.2.0/gems/psych-5.3.1/ext/psych/Makefile +3 -3
  296. data/vendor/bundle/ruby/3.2.0/gems/psych-5.3.1/lib/psych.so +0 -0
  297. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/CHANGELOG.md +649 -0
  298. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/Gemfile +16 -0
  299. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/LICENSE.txt +22 -0
  300. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/README.md +231 -0
  301. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/SECURITY.md +24 -0
  302. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/data/list.txt +16298 -0
  303. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/domain.rb +235 -0
  304. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/errors.rb +41 -0
  305. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/list.rb +247 -0
  306. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/rule.rb +350 -0
  307. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/version.rb +14 -0
  308. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix.rb +177 -0
  309. data/vendor/bundle/ruby/3.2.0/gems/racc-1.8.1/ext/racc/cparse/Makefile +3 -3
  310. data/vendor/bundle/ruby/3.2.0/gems/racc-1.8.1/lib/racc/cparse.so +0 -0
  311. data/vendor/bundle/ruby/3.2.0/gems/redcarpet-3.6.1/ext/redcarpet/Makefile +3 -3
  312. data/vendor/bundle/ruby/3.2.0/gems/redcarpet-3.6.1/lib/redcarpet.so +0 -0
  313. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/LICENSE.txt +22 -0
  314. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/NEWS.md +843 -0
  315. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/README.md +57 -0
  316. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/context.rdoc +143 -0
  317. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/child.rdoc +87 -0
  318. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/document.rdoc +276 -0
  319. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/element.rdoc +602 -0
  320. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/node.rdoc +97 -0
  321. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/parent.rdoc +267 -0
  322. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/child_toc.rdoc +12 -0
  323. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/document_toc.rdoc +30 -0
  324. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/element_toc.rdoc +55 -0
  325. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/master_toc.rdoc +135 -0
  326. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/node_toc.rdoc +16 -0
  327. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/parent_toc.rdoc +25 -0
  328. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tutorial.rdoc +1358 -0
  329. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/attlistdecl.rb +63 -0
  330. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/attribute.rb +210 -0
  331. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/cdata.rb +68 -0
  332. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/child.rb +96 -0
  333. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/comment.rb +80 -0
  334. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/doctype.rb +306 -0
  335. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/document.rb +471 -0
  336. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/attlistdecl.rb +11 -0
  337. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/dtd.rb +47 -0
  338. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/elementdecl.rb +18 -0
  339. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/entitydecl.rb +57 -0
  340. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/notationdecl.rb +40 -0
  341. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/element.rb +2578 -0
  342. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/encoding.rb +48 -0
  343. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/entity.rb +142 -0
  344. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/default.rb +116 -0
  345. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/pretty.rb +142 -0
  346. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/transitive.rb +58 -0
  347. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/functions.rb +446 -0
  348. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/instruction.rb +79 -0
  349. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/light/node.rb +188 -0
  350. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/namespace.rb +63 -0
  351. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/node.rb +80 -0
  352. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/output.rb +30 -0
  353. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parent.rb +166 -0
  354. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parseexception.rb +53 -0
  355. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/baseparser.rb +949 -0
  356. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/lightparser.rb +59 -0
  357. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/pullparser.rb +213 -0
  358. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/sax2parser.rb +270 -0
  359. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/streamparser.rb +67 -0
  360. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/treeparser.rb +89 -0
  361. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/ultralightparser.rb +57 -0
  362. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/xpathparser.rb +739 -0
  363. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/quickpath.rb +267 -0
  364. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/rexml.rb +39 -0
  365. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/sax2listener.rb +98 -0
  366. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/security.rb +28 -0
  367. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/source.rb +388 -0
  368. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/streamlistener.rb +93 -0
  369. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/text.rb +420 -0
  370. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/undefinednamespaceexception.rb +9 -0
  371. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/relaxng.rb +540 -0
  372. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/validation.rb +144 -0
  373. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/validationexception.rb +10 -0
  374. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xmldecl.rb +130 -0
  375. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xmltokens.rb +85 -0
  376. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xpath.rb +70 -0
  377. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xpath_parser.rb +980 -0
  378. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml.rb +3 -0
  379. data/vendor/bundle/ruby/3.2.0/gems/stringio-3.2.0/ext/stringio/Makefile +3 -3
  380. data/vendor/bundle/ruby/3.2.0/gems/stringio-3.2.0/lib/stringio.so +0 -0
  381. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/CHANGELOG.md +2148 -0
  382. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/LICENSE +20 -0
  383. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/README.md +1229 -0
  384. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/api.rb +111 -0
  385. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/assertion_failure.rb +13 -0
  386. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/callback_registry.rb +37 -0
  387. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/config.rb +20 -0
  388. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/cucumber.rb +12 -0
  389. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/deprecation.rb +11 -0
  390. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/errors.rb +19 -0
  391. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +228 -0
  392. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/curb_adapter.rb +354 -0
  393. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +239 -0
  394. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/excon_adapter.rb +167 -0
  395. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_lib_adapter.rb +9 -0
  396. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +21 -0
  397. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
  398. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/request.rb +28 -0
  399. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/response.rb +95 -0
  400. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/streamer.rb +44 -0
  401. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/webmock.rb +77 -0
  402. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb_adapter.rb +39 -0
  403. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/httpclient_adapter.rb +260 -0
  404. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/manticore_adapter.rb +147 -0
  405. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/net_http.rb +310 -0
  406. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/net_http_response.rb +36 -0
  407. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/patron_adapter.rb +132 -0
  408. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +190 -0
  409. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/any_arg_matcher.rb +15 -0
  410. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_argument_matcher.rb +23 -0
  411. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_excluding_matcher.rb +17 -0
  412. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_including_matcher.rb +19 -0
  413. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/minitest.rb +43 -0
  414. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rack_response.rb +73 -0
  415. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_body_diff.rb +66 -0
  416. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_execution_verifier.rb +79 -0
  417. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_pattern.rb +428 -0
  418. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_registry.rb +37 -0
  419. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_signature.rb +56 -0
  420. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_signature_snippet.rb +63 -0
  421. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_stub.rb +134 -0
  422. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/response.rb +161 -0
  423. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/responses_sequence.rb +42 -0
  424. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers/request_pattern_matcher.rb +80 -0
  425. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers/webmock_matcher.rb +69 -0
  426. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers.rb +29 -0
  427. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec.rb +44 -0
  428. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/stub_registry.rb +84 -0
  429. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/stub_request_snippet.rb +40 -0
  430. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/test_unit.rb +22 -0
  431. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_counter.rb +45 -0
  432. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_keys_stringifier.rb +27 -0
  433. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_validator.rb +19 -0
  434. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/headers.rb +77 -0
  435. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/json.rb +72 -0
  436. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/parse_error.rb +7 -0
  437. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/xml.rb +16 -0
  438. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/query_mapper.rb +283 -0
  439. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/uri.rb +113 -0
  440. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/values_stringifier.rb +22 -0
  441. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/version_checker.rb +113 -0
  442. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/version.rb +5 -0
  443. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/webmock.rb +175 -0
  444. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock.rb +61 -0
  445. data/vendor/bundle/ruby/3.2.0/gems/websocket-driver-0.8.0/ext/websocket-driver/Makefile +3 -3
  446. data/vendor/bundle/ruby/3.2.0/gems/websocket-driver-0.8.0/lib/websocket_mask.so +0 -0
  447. data/vendor/bundle/ruby/3.2.0/specifications/addressable-2.9.0.gemspec +29 -0
  448. data/vendor/bundle/ruby/3.2.0/specifications/crack-1.0.1.gemspec +27 -0
  449. data/vendor/bundle/ruby/3.2.0/specifications/faraday-2.14.1.gemspec +0 -0
  450. data/vendor/bundle/ruby/3.2.0/specifications/faraday-net_http-3.4.2.gemspec +26 -0
  451. data/vendor/bundle/ruby/3.2.0/specifications/hashdiff-1.2.1.gemspec +30 -0
  452. data/vendor/bundle/ruby/3.2.0/specifications/net-http-0.9.1.gemspec +27 -0
  453. data/vendor/bundle/ruby/3.2.0/specifications/public_suffix-7.0.5.gemspec +24 -0
  454. data/vendor/bundle/ruby/3.2.0/specifications/rexml-3.4.4.gemspec +25 -0
  455. data/vendor/bundle/ruby/3.2.0/specifications/webmock-3.26.2.gemspec +44 -0
  456. metadata +377 -2
@@ -0,0 +1,1040 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (C) Bob Aman
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+
20
+ require "addressable/version"
21
+ require "addressable/uri"
22
+
23
+ module Addressable
24
+ ##
25
+ # This is an implementation of a URI template based on
26
+ # RFC 6570 (http://tools.ietf.org/html/rfc6570).
27
+ class Template
28
+ # Constants used throughout the template code.
29
+ anything =
30
+ Addressable::URI::CharacterClasses::RESERVED +
31
+ Addressable::URI::CharacterClasses::UNRESERVED
32
+
33
+
34
+ variable_char_class =
35
+ Addressable::URI::CharacterClasses::ALPHA +
36
+ Addressable::URI::CharacterClasses::DIGIT + '_'
37
+
38
+ var_char =
39
+ "(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
40
+ RESERVED =
41
+ "(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])"
42
+ RESERVED_NO_COMMA =
43
+ "(?:[#{anything.delete(',')}]|%[a-fA-F0-9][a-fA-F0-9])"
44
+ UNRESERVED =
45
+ "(?:[#{
46
+ Addressable::URI::CharacterClasses::UNRESERVED
47
+ }]|%[a-fA-F0-9][a-fA-F0-9])"
48
+ variable =
49
+ "(?:#{var_char}(?:\\.?#{var_char})*)"
50
+ varspec =
51
+ "(?:(#{variable})(\\*|:\\d+)?)"
52
+ VARNAME =
53
+ /^#{variable}$/
54
+ VARSPEC =
55
+ /^#{varspec}$/
56
+ VARIABLE_LIST =
57
+ /^#{varspec}(?:,#{varspec})*$/
58
+ operator =
59
+ "+#./;?&=,!@|"
60
+ EXPRESSION =
61
+ /\{([#{operator}])?(#{varspec}(?:,#{varspec})*)\}/
62
+
63
+
64
+ LEADERS = {
65
+ '?' => '?',
66
+ '/' => '/',
67
+ '#' => '#',
68
+ '.' => '.',
69
+ ';' => ';',
70
+ '&' => '&'
71
+ }
72
+ JOINERS = {
73
+ '?' => '&',
74
+ '.' => '.',
75
+ ';' => ';',
76
+ '&' => '&',
77
+ '/' => '/'
78
+ }
79
+
80
+ ##
81
+ # Raised if an invalid template value is supplied.
82
+ class InvalidTemplateValueError < StandardError
83
+ end
84
+
85
+ ##
86
+ # Raised if an invalid template operator is used in a pattern.
87
+ class InvalidTemplateOperatorError < StandardError
88
+ end
89
+
90
+ ##
91
+ # Raised if an invalid template operator is used in a pattern.
92
+ class TemplateOperatorAbortedError < StandardError
93
+ end
94
+
95
+ ##
96
+ # This class represents the data that is extracted when a Template
97
+ # is matched against a URI.
98
+ class MatchData
99
+ ##
100
+ # Creates a new MatchData object.
101
+ # MatchData objects should never be instantiated directly.
102
+ #
103
+ # @param [Addressable::URI] uri
104
+ # The URI that the template was matched against.
105
+ def initialize(uri, template, mapping)
106
+ @uri = uri.dup.freeze
107
+ @template = template
108
+ @mapping = mapping.dup.freeze
109
+ end
110
+
111
+ ##
112
+ # @return [Addressable::URI]
113
+ # The URI that the Template was matched against.
114
+ attr_reader :uri
115
+
116
+ ##
117
+ # @return [Addressable::Template]
118
+ # The Template used for the match.
119
+ attr_reader :template
120
+
121
+ ##
122
+ # @return [Hash]
123
+ # The mapping that resulted from the match.
124
+ # Note that this mapping does not include keys or values for
125
+ # variables that appear in the Template, but are not present
126
+ # in the URI.
127
+ attr_reader :mapping
128
+
129
+ ##
130
+ # @return [Array]
131
+ # The list of variables that were present in the Template.
132
+ # Note that this list will include variables which do not appear
133
+ # in the mapping because they were not present in URI.
134
+ def variables
135
+ self.template.variables
136
+ end
137
+ alias_method :keys, :variables
138
+ alias_method :names, :variables
139
+
140
+ ##
141
+ # @return [Array]
142
+ # The list of values that were captured by the Template.
143
+ # Note that this list will include nils for any variables which
144
+ # were in the Template, but did not appear in the URI.
145
+ def values
146
+ @values ||= self.variables.inject([]) do |accu, key|
147
+ accu << self.mapping[key]
148
+ accu
149
+ end
150
+ end
151
+ alias_method :captures, :values
152
+
153
+ ##
154
+ # Accesses captured values by name or by index.
155
+ #
156
+ # @param [String, Symbol, Fixnum] key
157
+ # Capture index or name. Note that when accessing by with index
158
+ # of 0, the full URI will be returned. The intention is to mimic
159
+ # the ::MatchData#[] behavior.
160
+ #
161
+ # @param [#to_int, nil] len
162
+ # If provided, an array of values will be returned with the given
163
+ # parameter used as length.
164
+ #
165
+ # @return [Array, String, nil]
166
+ # The captured value corresponding to the index or name. If the
167
+ # value was not provided or the key is unknown, nil will be
168
+ # returned.
169
+ #
170
+ # If the second parameter is provided, an array of that length will
171
+ # be returned instead.
172
+ def [](key, len = nil)
173
+ if len
174
+ to_a[key, len]
175
+ elsif String === key or Symbol === key
176
+ mapping[key.to_s]
177
+ else
178
+ to_a[key]
179
+ end
180
+ end
181
+
182
+ ##
183
+ # @return [Array]
184
+ # Array with the matched URI as first element followed by the captured
185
+ # values.
186
+ def to_a
187
+ [to_s, *values]
188
+ end
189
+
190
+ ##
191
+ # @return [String]
192
+ # The matched URI as String.
193
+ def to_s
194
+ uri.to_s
195
+ end
196
+ alias_method :string, :to_s
197
+
198
+ # Returns multiple captured values at once.
199
+ #
200
+ # @param [String, Symbol, Fixnum] *indexes
201
+ # Indices of the captures to be returned
202
+ #
203
+ # @return [Array]
204
+ # Values corresponding to given indices.
205
+ #
206
+ # @see Addressable::Template::MatchData#[]
207
+ def values_at(*indexes)
208
+ indexes.map { |i| self[i] }
209
+ end
210
+
211
+ ##
212
+ # Returns a <tt>String</tt> representation of the MatchData's state.
213
+ #
214
+ # @return [String] The MatchData's state, as a <tt>String</tt>.
215
+ def inspect
216
+ sprintf("#<%s:%#0x RESULT:%s>",
217
+ self.class.to_s, self.object_id, self.mapping.inspect)
218
+ end
219
+
220
+ ##
221
+ # Dummy method for code expecting a ::MatchData instance
222
+ #
223
+ # @return [String] An empty string.
224
+ def pre_match
225
+ ""
226
+ end
227
+ alias_method :post_match, :pre_match
228
+ end
229
+
230
+ ##
231
+ # Creates a new <tt>Addressable::Template</tt> object.
232
+ #
233
+ # @param [#to_str] pattern The URI Template pattern.
234
+ #
235
+ # @return [Addressable::Template] The initialized Template object.
236
+ def initialize(pattern)
237
+ if !pattern.respond_to?(:to_str)
238
+ raise TypeError, "Can't convert #{pattern.class} into String."
239
+ end
240
+ @pattern = pattern.to_str.dup.freeze
241
+ end
242
+
243
+ ##
244
+ # Freeze URI, initializing instance variables.
245
+ #
246
+ # @return [Addressable::URI] The frozen URI object.
247
+ def freeze
248
+ self.variables
249
+ self.variable_defaults
250
+ self.named_captures
251
+ super
252
+ end
253
+
254
+ ##
255
+ # @return [String] The Template object's pattern.
256
+ attr_reader :pattern
257
+
258
+ ##
259
+ # Returns a <tt>String</tt> representation of the Template object's state.
260
+ #
261
+ # @return [String] The Template object's state, as a <tt>String</tt>.
262
+ def inspect
263
+ sprintf("#<%s:%#0x PATTERN:%s>",
264
+ self.class.to_s, self.object_id, self.pattern)
265
+ end
266
+
267
+ ##
268
+ # Returns <code>true</code> if the Template objects are equal. This method
269
+ # does NOT normalize either Template before doing the comparison.
270
+ #
271
+ # @param [Object] template The Template to compare.
272
+ #
273
+ # @return [TrueClass, FalseClass]
274
+ # <code>true</code> if the Templates are equivalent, <code>false</code>
275
+ # otherwise.
276
+ def ==(template)
277
+ return false unless template.kind_of?(Template)
278
+ return self.pattern == template.pattern
279
+ end
280
+
281
+ ##
282
+ # Addressable::Template makes no distinction between `==` and `eql?`.
283
+ #
284
+ # @see #==
285
+ alias_method :eql?, :==
286
+
287
+ ##
288
+ # Extracts a mapping from the URI using a URI Template pattern.
289
+ #
290
+ # @param [Addressable::URI, #to_str] uri
291
+ # The URI to extract from.
292
+ #
293
+ # @param [#restore, #match] processor
294
+ # A template processor object may optionally be supplied.
295
+ #
296
+ # The object should respond to either the <tt>restore</tt> or
297
+ # <tt>match</tt> messages or both. The <tt>restore</tt> method should
298
+ # take two parameters: `[String] name` and `[String] value`.
299
+ # The <tt>restore</tt> method should reverse any transformations that
300
+ # have been performed on the value to ensure a valid URI.
301
+ # The <tt>match</tt> method should take a single
302
+ # parameter: `[String] name`. The <tt>match</tt> method should return
303
+ # a <tt>String</tt> containing a regular expression capture group for
304
+ # matching on that particular variable. The default value is `".*?"`.
305
+ # The <tt>match</tt> method has no effect on multivariate operator
306
+ # expansions.
307
+ #
308
+ # @return [Hash, NilClass]
309
+ # The <tt>Hash</tt> mapping that was extracted from the URI, or
310
+ # <tt>nil</tt> if the URI didn't match the template.
311
+ #
312
+ # @example
313
+ # class ExampleProcessor
314
+ # def self.restore(name, value)
315
+ # return value.gsub(/\+/, " ") if name == "query"
316
+ # return value
317
+ # end
318
+ #
319
+ # def self.match(name)
320
+ # return ".*?" if name == "first"
321
+ # return ".*"
322
+ # end
323
+ # end
324
+ #
325
+ # uri = Addressable::URI.parse(
326
+ # "http://example.com/search/an+example+search+query/"
327
+ # )
328
+ # Addressable::Template.new(
329
+ # "http://example.com/search/{query}/"
330
+ # ).extract(uri, ExampleProcessor)
331
+ # #=> {"query" => "an example search query"}
332
+ #
333
+ # uri = Addressable::URI.parse("http://example.com/a/b/c/")
334
+ # Addressable::Template.new(
335
+ # "http://example.com/{first}/{second}/"
336
+ # ).extract(uri, ExampleProcessor)
337
+ # #=> {"first" => "a", "second" => "b/c"}
338
+ #
339
+ # uri = Addressable::URI.parse("http://example.com/a/b/c/")
340
+ # Addressable::Template.new(
341
+ # "http://example.com/{first}/{-list|/|second}/"
342
+ # ).extract(uri)
343
+ # #=> {"first" => "a", "second" => ["b", "c"]}
344
+ def extract(uri, processor=nil)
345
+ match_data = self.match(uri, processor)
346
+ return (match_data ? match_data.mapping : nil)
347
+ end
348
+
349
+ ##
350
+ # Extracts match data from the URI using a URI Template pattern.
351
+ #
352
+ # @param [Addressable::URI, #to_str] uri
353
+ # The URI to extract from.
354
+ #
355
+ # @param [#restore, #match] processor
356
+ # A template processor object may optionally be supplied.
357
+ #
358
+ # The object should respond to either the <tt>restore</tt> or
359
+ # <tt>match</tt> messages or both. The <tt>restore</tt> method should
360
+ # take two parameters: `[String] name` and `[String] value`.
361
+ # The <tt>restore</tt> method should reverse any transformations that
362
+ # have been performed on the value to ensure a valid URI.
363
+ # The <tt>match</tt> method should take a single
364
+ # parameter: `[String] name`. The <tt>match</tt> method should return
365
+ # a <tt>String</tt> containing a regular expression capture group for
366
+ # matching on that particular variable. The default value is `".*?"`.
367
+ # The <tt>match</tt> method has no effect on multivariate operator
368
+ # expansions.
369
+ #
370
+ # @return [Hash, NilClass]
371
+ # The <tt>Hash</tt> mapping that was extracted from the URI, or
372
+ # <tt>nil</tt> if the URI didn't match the template.
373
+ #
374
+ # @example
375
+ # class ExampleProcessor
376
+ # def self.restore(name, value)
377
+ # return value.gsub(/\+/, " ") if name == "query"
378
+ # return value
379
+ # end
380
+ #
381
+ # def self.match(name)
382
+ # return ".*?" if name == "first"
383
+ # return ".*"
384
+ # end
385
+ # end
386
+ #
387
+ # uri = Addressable::URI.parse(
388
+ # "http://example.com/search/an+example+search+query/"
389
+ # )
390
+ # match = Addressable::Template.new(
391
+ # "http://example.com/search/{query}/"
392
+ # ).match(uri, ExampleProcessor)
393
+ # match.variables
394
+ # #=> ["query"]
395
+ # match.captures
396
+ # #=> ["an example search query"]
397
+ #
398
+ # uri = Addressable::URI.parse("http://example.com/a/b/c/")
399
+ # match = Addressable::Template.new(
400
+ # "http://example.com/{first}/{+second}/"
401
+ # ).match(uri, ExampleProcessor)
402
+ # match.variables
403
+ # #=> ["first", "second"]
404
+ # match.captures
405
+ # #=> ["a", "b/c"]
406
+ #
407
+ # uri = Addressable::URI.parse("http://example.com/a/b/c/")
408
+ # match = Addressable::Template.new(
409
+ # "http://example.com/{first}{/second*}/"
410
+ # ).match(uri)
411
+ # match.variables
412
+ # #=> ["first", "second"]
413
+ # match.captures
414
+ # #=> ["a", ["b", "c"]]
415
+ def match(uri, processor=nil)
416
+ uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
417
+ mapping = {}
418
+
419
+ # First, we need to process the pattern, and extract the values.
420
+ expansions, expansion_regexp =
421
+ parse_template_pattern(pattern, processor)
422
+
423
+ return nil unless uri.to_str.match(expansion_regexp)
424
+ unparsed_values = uri.to_str.scan(expansion_regexp).flatten
425
+
426
+ if uri.to_str == pattern
427
+ return Addressable::Template::MatchData.new(uri, self, mapping)
428
+ elsif expansions.size > 0
429
+ index = 0
430
+ expansions.each do |expansion|
431
+ _, operator, varlist = *expansion.match(EXPRESSION)
432
+ varlist.split(',').each do |varspec|
433
+ _, name, modifier = *varspec.match(VARSPEC)
434
+ mapping[name] ||= nil
435
+ case operator
436
+ when nil, '+', '#', '/', '.'
437
+ unparsed_value = unparsed_values[index]
438
+ name = varspec[VARSPEC, 1]
439
+ value = unparsed_value
440
+ value = value.split(JOINERS[operator]) if value && modifier == '*'
441
+ when ';', '?', '&'
442
+ if modifier == '*'
443
+ if unparsed_values[index]
444
+ value = unparsed_values[index].split(JOINERS[operator])
445
+ value = value.inject({}) do |acc, v|
446
+ key, val = v.split('=')
447
+ val = "" if val.nil?
448
+ acc[key] = val
449
+ acc
450
+ end
451
+ end
452
+ else
453
+ if (unparsed_values[index])
454
+ name, value = unparsed_values[index].split('=')
455
+ value = "" if value.nil?
456
+ end
457
+ end
458
+ end
459
+ if processor != nil && processor.respond_to?(:restore)
460
+ value = processor.restore(name, value)
461
+ end
462
+ if processor == nil
463
+ if value.is_a?(Hash)
464
+ value = value.inject({}){|acc, (k, v)|
465
+ acc[Addressable::URI.unencode_component(k)] =
466
+ Addressable::URI.unencode_component(v)
467
+ acc
468
+ }
469
+ elsif value.is_a?(Array)
470
+ value = value.map{|v| Addressable::URI.unencode_component(v) }
471
+ else
472
+ value = Addressable::URI.unencode_component(value)
473
+ end
474
+ end
475
+ if !mapping.has_key?(name) || mapping[name].nil?
476
+ # Doesn't exist, set to value (even if value is nil)
477
+ mapping[name] = value
478
+ end
479
+ index = index + 1
480
+ end
481
+ end
482
+ return Addressable::Template::MatchData.new(uri, self, mapping)
483
+ else
484
+ return nil
485
+ end
486
+ end
487
+
488
+ ##
489
+ # Expands a URI template into another URI template.
490
+ #
491
+ # @param [Hash] mapping The mapping that corresponds to the pattern.
492
+ # @param [#validate, #transform] processor
493
+ # An optional processor object may be supplied.
494
+ # @param [Boolean] normalize_values
495
+ # Optional flag to enable/disable unicode normalization. Default: true
496
+ #
497
+ # The object should respond to either the <tt>validate</tt> or
498
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
499
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
500
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
501
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
502
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
503
+ # exception will be raised if the value is invalid. The <tt>transform</tt>
504
+ # method should return the transformed variable value as a <tt>String</tt>.
505
+ # If a <tt>transform</tt> method is used, the value will not be percent
506
+ # encoded automatically. Unicode normalization will be performed both
507
+ # before and after sending the value to the transform method.
508
+ #
509
+ # @return [Addressable::Template] The partially expanded URI template.
510
+ #
511
+ # @example
512
+ # Addressable::Template.new(
513
+ # "http://example.com/{one}/{two}/"
514
+ # ).partial_expand({"one" => "1"}).pattern
515
+ # #=> "http://example.com/1/{two}/"
516
+ #
517
+ # Addressable::Template.new(
518
+ # "http://example.com/{?one,two}/"
519
+ # ).partial_expand({"one" => "1"}).pattern
520
+ # #=> "http://example.com/?one=1{&two}/"
521
+ #
522
+ # Addressable::Template.new(
523
+ # "http://example.com/{?one,two,three}/"
524
+ # ).partial_expand({"one" => "1", "three" => 3}).pattern
525
+ # #=> "http://example.com/?one=1{&two}&three=3"
526
+ def partial_expand(mapping, processor=nil, normalize_values=true)
527
+ result = self.pattern.dup
528
+ mapping = normalize_keys(mapping)
529
+ result.gsub!( EXPRESSION ) do |capture|
530
+ transform_partial_capture(mapping, capture, processor, normalize_values)
531
+ end
532
+ return Addressable::Template.new(result)
533
+ end
534
+
535
+ ##
536
+ # Expands a URI template into a full URI.
537
+ #
538
+ # @param [Hash] mapping The mapping that corresponds to the pattern.
539
+ # @param [#validate, #transform] processor
540
+ # An optional processor object may be supplied.
541
+ # @param [Boolean] normalize_values
542
+ # Optional flag to enable/disable unicode normalization. Default: true
543
+ #
544
+ # The object should respond to either the <tt>validate</tt> or
545
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
546
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
547
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
548
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
549
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
550
+ # exception will be raised if the value is invalid. The <tt>transform</tt>
551
+ # method should return the transformed variable value as a <tt>String</tt>.
552
+ # If a <tt>transform</tt> method is used, the value will not be percent
553
+ # encoded automatically. Unicode normalization will be performed both
554
+ # before and after sending the value to the transform method.
555
+ #
556
+ # @return [Addressable::URI] The expanded URI template.
557
+ #
558
+ # @example
559
+ # class ExampleProcessor
560
+ # def self.validate(name, value)
561
+ # return !!(value =~ /^[\w ]+$/) if name == "query"
562
+ # return true
563
+ # end
564
+ #
565
+ # def self.transform(name, value)
566
+ # return value.gsub(/ /, "+") if name == "query"
567
+ # return value
568
+ # end
569
+ # end
570
+ #
571
+ # Addressable::Template.new(
572
+ # "http://example.com/search/{query}/"
573
+ # ).expand(
574
+ # {"query" => "an example search query"},
575
+ # ExampleProcessor
576
+ # ).to_str
577
+ # #=> "http://example.com/search/an+example+search+query/"
578
+ #
579
+ # Addressable::Template.new(
580
+ # "http://example.com/search/{query}/"
581
+ # ).expand(
582
+ # {"query" => "an example search query"}
583
+ # ).to_str
584
+ # #=> "http://example.com/search/an%20example%20search%20query/"
585
+ #
586
+ # Addressable::Template.new(
587
+ # "http://example.com/search/{query}/"
588
+ # ).expand(
589
+ # {"query" => "bogus!"},
590
+ # ExampleProcessor
591
+ # ).to_str
592
+ # #=> Addressable::Template::InvalidTemplateValueError
593
+ def expand(mapping, processor=nil, normalize_values=true)
594
+ result = self.pattern.dup
595
+ mapping = normalize_keys(mapping)
596
+ result.gsub!( EXPRESSION ) do |capture|
597
+ transform_capture(mapping, capture, processor, normalize_values)
598
+ end
599
+ return Addressable::URI.parse(result)
600
+ end
601
+
602
+ ##
603
+ # Returns an Array of variables used within the template pattern.
604
+ # The variables are listed in the Array in the order they appear within
605
+ # the pattern. Multiple occurrences of a variable within a pattern are
606
+ # not represented in this Array.
607
+ #
608
+ # @return [Array] The variables present in the template's pattern.
609
+ def variables
610
+ @variables ||= ordered_variable_defaults.map { |var, val| var }.uniq
611
+ end
612
+ alias_method :keys, :variables
613
+ alias_method :names, :variables
614
+
615
+ ##
616
+ # Returns a mapping of variables to their default values specified
617
+ # in the template. Variables without defaults are not returned.
618
+ #
619
+ # @return [Hash] Mapping of template variables to their defaults
620
+ def variable_defaults
621
+ @variable_defaults ||=
622
+ Hash[*ordered_variable_defaults.reject { |k, v| v.nil? }.flatten]
623
+ end
624
+
625
+ ##
626
+ # Coerces a template into a `Regexp` object. This regular expression will
627
+ # behave very similarly to the actual template, and should match the same
628
+ # URI values, but it cannot fully handle, for example, values that would
629
+ # extract to an `Array`.
630
+ #
631
+ # @return [Regexp] A regular expression which should match the template.
632
+ def to_regexp
633
+ _, source = parse_template_pattern(pattern)
634
+ Regexp.new(source)
635
+ end
636
+
637
+ ##
638
+ # Returns the source of the coerced `Regexp`.
639
+ #
640
+ # @return [String] The source of the `Regexp` given by {#to_regexp}.
641
+ #
642
+ # @api private
643
+ def source
644
+ self.to_regexp.source
645
+ end
646
+
647
+ ##
648
+ # Returns the named captures of the coerced `Regexp`.
649
+ #
650
+ # @return [Hash] The named captures of the `Regexp` given by {#to_regexp}.
651
+ #
652
+ # @api private
653
+ def named_captures
654
+ self.to_regexp.named_captures
655
+ end
656
+
657
+ private
658
+ def ordered_variable_defaults
659
+ @ordered_variable_defaults ||= begin
660
+ expansions, _ = parse_template_pattern(pattern)
661
+ expansions.flat_map do |capture|
662
+ _, _, varlist = *capture.match(EXPRESSION)
663
+ varlist.split(',').map do |varspec|
664
+ varspec[VARSPEC, 1]
665
+ end
666
+ end
667
+ end
668
+ end
669
+
670
+
671
+ ##
672
+ # Loops through each capture and expands any values available in mapping
673
+ #
674
+ # @param [Hash] mapping
675
+ # Set of keys to expand
676
+ # @param [String] capture
677
+ # The expression to expand
678
+ # @param [#validate, #transform] processor
679
+ # An optional processor object may be supplied.
680
+ # @param [Boolean] normalize_values
681
+ # Optional flag to enable/disable unicode normalization. Default: true
682
+ #
683
+ # The object should respond to either the <tt>validate</tt> or
684
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
685
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
686
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
687
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
688
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception
689
+ # will be raised if the value is invalid. The <tt>transform</tt> method
690
+ # should return the transformed variable value as a <tt>String</tt>. If a
691
+ # <tt>transform</tt> method is used, the value will not be percent encoded
692
+ # automatically. Unicode normalization will be performed both before and
693
+ # after sending the value to the transform method.
694
+ #
695
+ # @return [String] The expanded expression
696
+ def transform_partial_capture(mapping, capture, processor = nil,
697
+ normalize_values = true)
698
+ _, operator, varlist = *capture.match(EXPRESSION)
699
+
700
+ vars = varlist.split(",")
701
+
702
+ if operator == "?"
703
+ # partial expansion of form style query variables sometimes requires a
704
+ # slight reordering of the variables to produce a valid url.
705
+ first_to_expand = vars.find { |varspec|
706
+ _, name, _ = *varspec.match(VARSPEC)
707
+ mapping.key?(name) && !mapping[name].nil?
708
+ }
709
+
710
+ vars = [first_to_expand] + vars.reject {|varspec| varspec == first_to_expand} if first_to_expand
711
+ end
712
+
713
+ vars.
714
+ inject("".dup) do |acc, varspec|
715
+ _, name, _ = *varspec.match(VARSPEC)
716
+ next_val = if mapping.key? name
717
+ transform_capture(mapping, "{#{operator}#{varspec}}",
718
+ processor, normalize_values)
719
+ else
720
+ "{#{operator}#{varspec}}"
721
+ end
722
+ # If we've already expanded at least one '?' operator with non-empty
723
+ # value, change to '&'
724
+ operator = "&" if (operator == "?") && (next_val != "")
725
+ acc << next_val
726
+ end
727
+ end
728
+
729
+ ##
730
+ # Transforms a mapped value so that values can be substituted into the
731
+ # template.
732
+ #
733
+ # @param [Hash] mapping The mapping to replace captures
734
+ # @param [String] capture
735
+ # The expression to replace
736
+ # @param [#validate, #transform] processor
737
+ # An optional processor object may be supplied.
738
+ # @param [Boolean] normalize_values
739
+ # Optional flag to enable/disable unicode normalization. Default: true
740
+ #
741
+ #
742
+ # The object should respond to either the <tt>validate</tt> or
743
+ # <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
744
+ # <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
745
+ # <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
746
+ # or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
747
+ # <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception
748
+ # will be raised if the value is invalid. The <tt>transform</tt> method
749
+ # should return the transformed variable value as a <tt>String</tt>. If a
750
+ # <tt>transform</tt> method is used, the value will not be percent encoded
751
+ # automatically. Unicode normalization will be performed both before and
752
+ # after sending the value to the transform method.
753
+ #
754
+ # @return [String] The expanded expression
755
+ def transform_capture(mapping, capture, processor=nil,
756
+ normalize_values=true)
757
+ _, operator, varlist = *capture.match(EXPRESSION)
758
+ return_value = varlist.split(',').inject([]) do |acc, varspec|
759
+ _, name, modifier = *varspec.match(VARSPEC)
760
+ value = mapping[name]
761
+ unless value == nil || value == {}
762
+ allow_reserved = %w(+ #).include?(operator)
763
+ # Common primitives where the .to_s output is well-defined
764
+ if Numeric === value || Symbol === value ||
765
+ value == true || value == false
766
+ value = value.to_s
767
+ end
768
+ length = modifier.gsub(':', '').to_i if modifier =~ /^:\d+/
769
+
770
+ unless (Hash === value) ||
771
+ value.respond_to?(:to_ary) || value.respond_to?(:to_str)
772
+ raise TypeError,
773
+ "Can't convert #{value.class} into String or Array."
774
+ end
775
+
776
+ value = normalize_value(value) if normalize_values
777
+
778
+ if processor == nil || !processor.respond_to?(:transform)
779
+ # Handle percent escaping
780
+ if allow_reserved
781
+ encode_map =
782
+ Addressable::URI::CharacterClasses::RESERVED +
783
+ Addressable::URI::CharacterClasses::UNRESERVED
784
+ else
785
+ encode_map = Addressable::URI::CharacterClasses::UNRESERVED
786
+ end
787
+ if value.kind_of?(Array)
788
+ transformed_value = value.map do |val|
789
+ if length
790
+ Addressable::URI.encode_component(val[0...length], encode_map)
791
+ else
792
+ Addressable::URI.encode_component(val, encode_map)
793
+ end
794
+ end
795
+ unless modifier == "*"
796
+ transformed_value = transformed_value.join(',')
797
+ end
798
+ elsif value.kind_of?(Hash)
799
+ transformed_value = value.map do |key, val|
800
+ if modifier == "*"
801
+ "#{
802
+ Addressable::URI.encode_component( key, encode_map)
803
+ }=#{
804
+ Addressable::URI.encode_component( val, encode_map)
805
+ }"
806
+ else
807
+ "#{
808
+ Addressable::URI.encode_component( key, encode_map)
809
+ },#{
810
+ Addressable::URI.encode_component( val, encode_map)
811
+ }"
812
+ end
813
+ end
814
+ unless modifier == "*"
815
+ transformed_value = transformed_value.join(',')
816
+ end
817
+ else
818
+ if length
819
+ transformed_value = Addressable::URI.encode_component(
820
+ value[0...length], encode_map)
821
+ else
822
+ transformed_value = Addressable::URI.encode_component(
823
+ value, encode_map)
824
+ end
825
+ end
826
+ end
827
+
828
+ # Process, if we've got a processor
829
+ if processor != nil
830
+ if processor.respond_to?(:validate)
831
+ if !processor.validate(name, value)
832
+ display_value = value.kind_of?(Array) ? value.inspect : value
833
+ raise InvalidTemplateValueError,
834
+ "#{name}=#{display_value} is an invalid template value."
835
+ end
836
+ end
837
+ if processor.respond_to?(:transform)
838
+ transformed_value = processor.transform(name, value)
839
+ if normalize_values
840
+ transformed_value = normalize_value(transformed_value)
841
+ end
842
+ end
843
+ end
844
+ acc << [name, transformed_value]
845
+ end
846
+ acc
847
+ end
848
+ return "" if return_value.empty?
849
+ join_values(operator, return_value)
850
+ end
851
+
852
+ ##
853
+ # Takes a set of values, and joins them together based on the
854
+ # operator.
855
+ #
856
+ # @param [String, Nil] operator One of the operators from the set
857
+ # (?,&,+,#,;,/,.), or nil if there wasn't one.
858
+ # @param [Array] return_value
859
+ # The set of return values (as [variable_name, value] tuples) that will
860
+ # be joined together.
861
+ #
862
+ # @return [String] The transformed mapped value
863
+ def join_values(operator, return_value)
864
+ leader = LEADERS.fetch(operator, '')
865
+ joiner = JOINERS.fetch(operator, ',')
866
+ case operator
867
+ when '&', '?'
868
+ leader + return_value.map{|k,v|
869
+ if v.is_a?(Array) && v.first =~ /=/
870
+ v.join(joiner)
871
+ elsif v.is_a?(Array)
872
+ v.map{|inner_value| "#{k}=#{inner_value}"}.join(joiner)
873
+ else
874
+ "#{k}=#{v}"
875
+ end
876
+ }.join(joiner)
877
+ when ';'
878
+ return_value.map{|k,v|
879
+ if v.is_a?(Array) && v.first =~ /=/
880
+ ';' + v.join(";")
881
+ elsif v.is_a?(Array)
882
+ ';' + v.map{|inner_value| "#{k}=#{inner_value}"}.join(";")
883
+ else
884
+ v && v != '' ? ";#{k}=#{v}" : ";#{k}"
885
+ end
886
+ }.join
887
+ else
888
+ leader + return_value.map{|k,v| v}.join(joiner)
889
+ end
890
+ end
891
+
892
+ ##
893
+ # Takes a set of values, and joins them together based on the
894
+ # operator.
895
+ #
896
+ # @param [Hash, Array, String] value
897
+ # Normalizes unicode keys and values with String#unicode_normalize (NFC)
898
+ #
899
+ # @return [Hash, Array, String] The normalized values
900
+ def normalize_value(value)
901
+ # Handle unicode normalization
902
+ if value.respond_to?(:to_ary)
903
+ value.to_ary.map! { |val| normalize_value(val) }
904
+ elsif value.kind_of?(Hash)
905
+ value = value.inject({}) { |acc, (k, v)|
906
+ acc[normalize_value(k)] = normalize_value(v)
907
+ acc
908
+ }
909
+ else
910
+ value = value.to_s if !value.kind_of?(String)
911
+ if value.encoding != Encoding::UTF_8
912
+ value = value.dup.force_encoding(Encoding::UTF_8)
913
+ end
914
+ value = value.unicode_normalize(:nfc)
915
+ end
916
+ value
917
+ end
918
+
919
+ ##
920
+ # Generates a hash with string keys
921
+ #
922
+ # @param [Hash] mapping A mapping hash to normalize
923
+ #
924
+ # @return [Hash]
925
+ # A hash with stringified keys
926
+ def normalize_keys(mapping)
927
+ return mapping.inject({}) do |accu, pair|
928
+ name, value = pair
929
+ if Symbol === name
930
+ name = name.to_s
931
+ elsif name.respond_to?(:to_str)
932
+ name = name.to_str
933
+ else
934
+ raise TypeError,
935
+ "Can't convert #{name.class} into String."
936
+ end
937
+ accu[name] = value
938
+ accu
939
+ end
940
+ end
941
+
942
+ ##
943
+ # Generates the <tt>Regexp</tt> that parses a template pattern. Memoizes the
944
+ # value if template processor not set (processors may not be deterministic)
945
+ #
946
+ # @param [String] pattern The URI template pattern.
947
+ # @param [#match] processor The template processor to use.
948
+ #
949
+ # @return [Array, Regexp]
950
+ # An array of expansion variables nad a regular expression which may be
951
+ # used to parse a template pattern
952
+ def parse_template_pattern(pattern, processor = nil)
953
+ if processor.nil? && pattern == @pattern
954
+ @cached_template_parse ||=
955
+ parse_new_template_pattern(pattern, processor)
956
+ else
957
+ parse_new_template_pattern(pattern, processor)
958
+ end
959
+ end
960
+
961
+ ##
962
+ # Generates the <tt>Regexp</tt> that parses a template pattern.
963
+ #
964
+ # @param [String] pattern The URI template pattern.
965
+ # @param [#match] processor The template processor to use.
966
+ #
967
+ # @return [Array, Regexp]
968
+ # An array of expansion variables nad a regular expression which may be
969
+ # used to parse a template pattern
970
+ def parse_new_template_pattern(pattern, processor = nil)
971
+ # Escape the pattern. The two gsubs restore the escaped curly braces
972
+ # back to their original form. Basically, escape everything that isn't
973
+ # within an expansion.
974
+ escaped_pattern = Regexp.escape(
975
+ pattern
976
+ ).gsub(/\\\{(.*?)\\\}/) do |escaped|
977
+ escaped.gsub(/\\(.)/, "\\1")
978
+ end
979
+
980
+ expansions = []
981
+
982
+ # Create a regular expression that captures the values of the
983
+ # variables in the URI.
984
+ regexp_string = escaped_pattern.gsub( EXPRESSION ) do |expansion|
985
+
986
+ expansions << expansion
987
+ _, operator, varlist = *expansion.match(EXPRESSION)
988
+ leader = Regexp.escape(LEADERS.fetch(operator, ''))
989
+ joiner = Regexp.escape(JOINERS.fetch(operator, ','))
990
+ varspecs = varlist.split(',')
991
+ combined = varspecs.map do |varspec|
992
+ _, name, modifier = *varspec.match(VARSPEC)
993
+
994
+ result = processor && processor.respond_to?(:match) ? processor.match(name) : nil
995
+ if result
996
+ "(?<#{name}>#{ result })"
997
+ else
998
+ group = case operator
999
+ when '+'
1000
+ "#{ RESERVED }*?"
1001
+ when '#'
1002
+ "#{ RESERVED }*?"
1003
+ when '/'
1004
+ "#{ UNRESERVED }*?"
1005
+ when '.'
1006
+ "#{ UNRESERVED.gsub('\.', '') }*?"
1007
+ when ';'
1008
+ "#{ UNRESERVED }*=?#{ UNRESERVED }*?"
1009
+ when '?'
1010
+ "#{ UNRESERVED }*=#{ UNRESERVED }*?"
1011
+ when '&'
1012
+ "#{ UNRESERVED }*=#{ UNRESERVED }*?"
1013
+ else
1014
+ "#{ UNRESERVED }*?"
1015
+ end
1016
+ if modifier == '*'
1017
+ seg = case operator
1018
+ when '+', '#' then "#{RESERVED_NO_COMMA}*+"
1019
+ else group
1020
+ end
1021
+ joiner_pattern = operator.nil? ? joiner : "#{joiner}?"
1022
+ "(?<#{name}>#{seg}(?:#{joiner_pattern}#{seg})*)?"
1023
+ elsif varspecs.size > 1 && (operator == '+' || operator == '#') &&
1024
+ varspec != varspecs.last
1025
+ "(?<#{name}>#{RESERVED_NO_COMMA}*+)?"
1026
+ else
1027
+ "(?<#{name}>#{group})?"
1028
+ end
1029
+ end
1030
+ end.join("#{joiner}?")
1031
+ "(?:|#{leader}#{combined})"
1032
+ end
1033
+
1034
+ # Ensure that the regular expression matches the whole URI.
1035
+ regexp_string = "\\A#{regexp_string}\\z"
1036
+ return expansions, Regexp.new(regexp_string)
1037
+ end
1038
+
1039
+ end
1040
+ end