atlas_engine 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 (298) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +123 -0
  3. data/Rakefile +20 -0
  4. data/app/assets/config/atlas_engine_manifest.js +3 -0
  5. data/app/assets/stylesheets/atlas_engine/application.css +15 -0
  6. data/app/concerns/atlas_engine/handles_blob.rb +26 -0
  7. data/app/concerns/atlas_engine/handles_interruption.rb +22 -0
  8. data/app/controllers/atlas_engine/application_controller.rb +7 -0
  9. data/app/controllers/atlas_engine/connectivity_controller.rb +21 -0
  10. data/app/controllers/atlas_engine/country_imports_controller.rb +73 -0
  11. data/app/controllers/atlas_engine/graphql_controller.rb +59 -0
  12. data/app/countries/atlas_engine/ar/country_profile.yml +9 -0
  13. data/app/countries/atlas_engine/at/address_importer/corrections/open_address/city_corrector.rb +23 -0
  14. data/app/countries/atlas_engine/at/country_profile.yml +24 -0
  15. data/app/countries/atlas_engine/at/index_configuration.yml +63 -0
  16. data/app/countries/atlas_engine/at/synonyms.yml +6 -0
  17. data/app/countries/atlas_engine/at/validation_transcriber/address_parser.rb +58 -0
  18. data/app/countries/atlas_engine/au/address_importer/open_address/filter.rb +26 -0
  19. data/app/countries/atlas_engine/au/address_importer/open_address/mapper.rb +41 -0
  20. data/app/countries/atlas_engine/au/country_profile.yml +13 -0
  21. data/app/countries/atlas_engine/au/synonyms.yml +209 -0
  22. data/app/countries/atlas_engine/au/validation_transcriber/address_parser.rb +121 -0
  23. data/app/countries/atlas_engine/be/country_profile.yml +12 -0
  24. data/app/countries/atlas_engine/bm/address_importer/corrections/open_address/city_alias_corrector.rb +38 -0
  25. data/app/countries/atlas_engine/bm/address_importer/open_address/mapper.rb +40 -0
  26. data/app/countries/atlas_engine/bm/country_profile.yml +12 -0
  27. data/app/countries/atlas_engine/br/country_profile.yml +4 -0
  28. data/app/countries/atlas_engine/ca/country_profile.yml +7 -0
  29. data/app/countries/atlas_engine/ca/synonyms.yml +1615 -0
  30. data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/city_corrector.rb +29 -0
  31. data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/locale_corrector.rb +74 -0
  32. data/app/countries/atlas_engine/ch/address_importer/open_address/mapper.rb +40 -0
  33. data/app/countries/atlas_engine/ch/country_profile.yml +15 -0
  34. data/app/countries/atlas_engine/ch/locales/de/country_profile.yml +15 -0
  35. data/app/countries/atlas_engine/ch/locales/de/index_configuration.yml +63 -0
  36. data/app/countries/atlas_engine/ch/locales/de/synonyms.yml +7 -0
  37. data/app/countries/atlas_engine/ch/locales/fr/synonyms.yml +21 -0
  38. data/app/countries/atlas_engine/cz/country_profile.yml +6 -0
  39. data/app/countries/atlas_engine/de/country_profile.yml +19 -0
  40. data/app/countries/atlas_engine/de/index_configuration.yml +64 -0
  41. data/app/countries/atlas_engine/de/synonyms.yml +2 -0
  42. data/app/countries/atlas_engine/de/validation_transcriber/address_parser.rb +19 -0
  43. data/app/countries/atlas_engine/dk/country_profile.yml +6 -0
  44. data/app/countries/atlas_engine/dk/synonyms.yml +3 -0
  45. data/app/countries/atlas_engine/dk/validation_transcriber/address_parser.rb +21 -0
  46. data/app/countries/atlas_engine/fo/country_profile.yml +5 -0
  47. data/app/countries/atlas_engine/fr/address_importer/corrections/open_address/city_corrector.rb +28 -0
  48. data/app/countries/atlas_engine/fr/country_profile.yml +13 -0
  49. data/app/countries/atlas_engine/fr/synonyms.yml +21 -0
  50. data/app/countries/atlas_engine/fr/validation_transcriber/address_parser.rb +34 -0
  51. data/app/countries/atlas_engine/gb/address_validation/es/query_builder.rb +98 -0
  52. data/app/countries/atlas_engine/gb/country_profile.yml +10 -0
  53. data/app/countries/atlas_engine/gb/validation_transcriber/full_address_parser.rb +164 -0
  54. data/app/countries/atlas_engine/gb/validation_transcriber/parsed_address.rb +120 -0
  55. data/app/countries/atlas_engine/gg/address_validation/validators/full_address/restrictions/unsupported_city.rb +39 -0
  56. data/app/countries/atlas_engine/gg/country_profile.yml +7 -0
  57. data/app/countries/atlas_engine/ie/country_profile.yml +3 -0
  58. data/app/countries/atlas_engine/it/address_importer/corrections/open_address/city_corrector.rb +27 -0
  59. data/app/countries/atlas_engine/it/address_importer/corrections/open_address/province_corrector.rb +29 -0
  60. data/app/countries/atlas_engine/it/address_importer/open_address/mapper.rb +42 -0
  61. data/app/countries/atlas_engine/it/country_profile.yml +11 -0
  62. data/app/countries/atlas_engine/jp/address_validation/es/data_mapper.rb +63 -0
  63. data/app/countries/atlas_engine/jp/country_profile.yml +6 -0
  64. data/app/countries/atlas_engine/kr/address_importer/open_address/mapper.rb +41 -0
  65. data/app/countries/atlas_engine/kr/country_profile.yml +11 -0
  66. data/app/countries/atlas_engine/li/address_importer/corrections/open_address/city_corrector.rb +25 -0
  67. data/app/countries/atlas_engine/li/country_profile.yml +21 -0
  68. data/app/countries/atlas_engine/li/index_configuration.yml +63 -0
  69. data/app/countries/atlas_engine/li/synonyms.yml +6 -0
  70. data/app/countries/atlas_engine/lt/country_profile.yml +6 -0
  71. data/app/countries/atlas_engine/lt/synonyms.yml +7 -0
  72. data/app/countries/atlas_engine/lt/validation_transcriber/address_parser.rb +24 -0
  73. data/app/countries/atlas_engine/lu/address_importer/corrections/open_address/locale_corrector.rb +54 -0
  74. data/app/countries/atlas_engine/lu/country_profile.yml +12 -0
  75. data/app/countries/atlas_engine/nl/address_importer/corrections/open_address/city_corrector.rb +25 -0
  76. data/app/countries/atlas_engine/nl/country_profile.yml +18 -0
  77. data/app/countries/atlas_engine/nl/index_configuration.yml +52 -0
  78. data/app/countries/atlas_engine/nl/synonyms.yml +92 -0
  79. data/app/countries/atlas_engine/nl/validation_transcriber/address_parser.rb +85 -0
  80. data/app/countries/atlas_engine/no/country_profile.yml +5 -0
  81. data/app/countries/atlas_engine/nz/country_profile.yml +3 -0
  82. data/app/countries/atlas_engine/pl/country_profile.yml +5 -0
  83. data/app/countries/atlas_engine/pl/validation_transcriber/address_parser.rb +19 -0
  84. data/app/countries/atlas_engine/pt/address_importer/corrections/open_address/city_corrector.rb +32 -0
  85. data/app/countries/atlas_engine/pt/address_importer/open_address/mapper.rb +39 -0
  86. data/app/countries/atlas_engine/pt/country_profile.yml +10 -0
  87. data/app/countries/atlas_engine/pt/synonyms.yml +7 -0
  88. data/app/countries/atlas_engine/sa/country_profile.yml +10 -0
  89. data/app/countries/atlas_engine/se/country_profile.yml +5 -0
  90. data/app/countries/atlas_engine/tt/address_importer/open_address/mapper.rb +38 -0
  91. data/app/countries/atlas_engine/tt/country_profile.yml +7 -0
  92. data/app/countries/atlas_engine/us/country_profile.yml +12 -0
  93. data/app/countries/atlas_engine/us/synonyms.yml +350 -0
  94. data/app/graphql/atlas_engine/errors/locale_unsupported_error.rb +17 -0
  95. data/app/graphql/atlas_engine/schema.graphql +1293 -0
  96. data/app/graphql/atlas_engine/schema.rb +23 -0
  97. data/app/graphql/atlas_engine/types/address_validation/address_input.rb +51 -0
  98. data/app/graphql/atlas_engine/types/address_validation/concern_type.rb +20 -0
  99. data/app/graphql/atlas_engine/types/address_validation/enums/concern_enum.rb +15 -0
  100. data/app/graphql/atlas_engine/types/address_validation/field_type.rb +15 -0
  101. data/app/graphql/atlas_engine/types/address_validation/suggestion_type.rb +21 -0
  102. data/app/graphql/atlas_engine/types/base_argument.rb +9 -0
  103. data/app/graphql/atlas_engine/types/base_enum.rb +9 -0
  104. data/app/graphql/atlas_engine/types/base_field.rb +10 -0
  105. data/app/graphql/atlas_engine/types/base_input_object.rb +9 -0
  106. data/app/graphql/atlas_engine/types/base_interface.rb +10 -0
  107. data/app/graphql/atlas_engine/types/base_object.rb +9 -0
  108. data/app/graphql/atlas_engine/types/base_scalar.rb +9 -0
  109. data/app/graphql/atlas_engine/types/base_union.rb +9 -0
  110. data/app/graphql/atlas_engine/types/matching_strategy_type.rb +12 -0
  111. data/app/graphql/atlas_engine/types/mutation_type.rb +9 -0
  112. data/app/graphql/atlas_engine/types/query_type.rb +61 -0
  113. data/app/graphql/atlas_engine/types/validation_supported_country.rb +12 -0
  114. data/app/graphql/atlas_engine/types/validation_type.rb +22 -0
  115. data/app/helpers/atlas_engine/address_importer/import_log_helper.rb +66 -0
  116. data/app/helpers/atlas_engine/application_helper.rb +7 -0
  117. data/app/helpers/atlas_engine/locale_format_helper.rb +40 -0
  118. data/app/helpers/atlas_engine/log_base.rb +32 -0
  119. data/app/helpers/atlas_engine/log_helper.rb +24 -0
  120. data/app/helpers/atlas_engine/metrics_helper.rb +25 -0
  121. data/app/jobs/atlas_engine/address_importer/clear_records_job.rb +39 -0
  122. data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_job.rb +212 -0
  123. data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_launcher_job.rb +67 -0
  124. data/app/jobs/atlas_engine/address_importer/open_address/prepares_geo_json_file.rb +41 -0
  125. data/app/jobs/atlas_engine/address_importer/resumable_import_job.rb +49 -0
  126. data/app/jobs/atlas_engine/address_importer/street_backfill_job.rb +63 -0
  127. data/app/jobs/atlas_engine/application_job.rb +10 -0
  128. data/app/jobs/atlas_engine/concerns/address_importer/handles_errors.rb +43 -0
  129. data/app/lib/atlas_engine/concern_formatter.rb +40 -0
  130. data/app/lib/atlas_engine/restrictions/base.rb +20 -0
  131. data/app/lib/atlas_engine/restrictions/unsupported_script.rb +31 -0
  132. data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +201 -0
  133. data/app/lib/atlas_engine/validation_transcriber/address_parser_factory.rb +27 -0
  134. data/app/lib/atlas_engine/validation_transcriber/address_parser_north_america.rb +39 -0
  135. data/app/lib/atlas_engine/validation_transcriber/address_parser_oceanic.rb +17 -0
  136. data/app/lib/atlas_engine/validation_transcriber/address_parser_preprocessor.rb +132 -0
  137. data/app/lib/atlas_engine/validation_transcriber/address_parsing_helper.rb +38 -0
  138. data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +54 -0
  139. data/app/lib/atlas_engine/validation_transcriber/constants.rb +50 -0
  140. data/app/lib/atlas_engine/validation_transcriber/english_street_parser.rb +59 -0
  141. data/app/lib/atlas_engine/validation_transcriber/formatter.rb +46 -0
  142. data/app/lib/atlas_engine/validation_transcriber/french_street_parser.rb +50 -0
  143. data/app/lib/atlas_engine/validation_transcriber/province_code_normalizer.rb +45 -0
  144. data/app/lib/atlas_engine/validation_transcriber/street_parser.rb +18 -0
  145. data/app/lib/atlas_engine/validation_transcriber/zip_normalizer.rb +23 -0
  146. data/app/mailers/atlas_engine/application_mailer.rb +9 -0
  147. data/app/models/atlas_engine/address_importer/corrections/corrector.rb +33 -0
  148. data/app/models/atlas_engine/address_importer/import_events_notifier/base.rb +35 -0
  149. data/app/models/atlas_engine/address_importer/import_events_notifier/notifier.rb +26 -0
  150. data/app/models/atlas_engine/address_importer/open_address/default_mapper.rb +46 -0
  151. data/app/models/atlas_engine/address_importer/open_address/feature_helper.rb +110 -0
  152. data/app/models/atlas_engine/address_importer/open_address/filter.rb +17 -0
  153. data/app/models/atlas_engine/address_importer/open_address/loader.rb +27 -0
  154. data/app/models/atlas_engine/address_importer/open_address/transformer.rb +39 -0
  155. data/app/models/atlas_engine/address_importer/open_address.rb +10 -0
  156. data/app/models/atlas_engine/address_importer/validation/base_validator.rb +86 -0
  157. data/app/models/atlas_engine/address_importer/validation/default_validator.rb +27 -0
  158. data/app/models/atlas_engine/address_importer/validation/field_validations/city.rb +47 -0
  159. data/app/models/atlas_engine/address_importer/validation/field_validations/interface.rb +29 -0
  160. data/app/models/atlas_engine/address_importer/validation/field_validations/province.rb +73 -0
  161. data/app/models/atlas_engine/address_importer/validation/field_validations/zip.rb +84 -0
  162. data/app/models/atlas_engine/address_importer/validation/validator.rb +17 -0
  163. data/app/models/atlas_engine/address_importer/validation/wrapper.rb +70 -0
  164. data/app/models/atlas_engine/address_number.rb +36 -0
  165. data/app/models/atlas_engine/address_number_range.rb +200 -0
  166. data/app/models/atlas_engine/address_validation/abstract_address.rb +49 -0
  167. data/app/models/atlas_engine/address_validation/address.rb +47 -0
  168. data/app/models/atlas_engine/address_validation/candidate.rb +109 -0
  169. data/app/models/atlas_engine/address_validation/candidate_tuple.rb +15 -0
  170. data/app/models/atlas_engine/address_validation/concern.rb +74 -0
  171. data/app/models/atlas_engine/address_validation/concern_producer.rb +19 -0
  172. data/app/models/atlas_engine/address_validation/concern_queue.rb +20 -0
  173. data/app/models/atlas_engine/address_validation/concern_record.rb +122 -0
  174. data/app/models/atlas_engine/address_validation/datastore_base.rb +27 -0
  175. data/app/models/atlas_engine/address_validation/errors.rb +13 -0
  176. data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +70 -0
  177. data/app/models/atlas_engine/address_validation/es/data_mappers/decompounding_data_mapper.rb +39 -0
  178. data/app/models/atlas_engine/address_validation/es/data_mappers/default_data_mapper.rb +110 -0
  179. data/app/models/atlas_engine/address_validation/es/datastore.rb +229 -0
  180. data/app/models/atlas_engine/address_validation/es/default_query_builder.rb +30 -0
  181. data/app/models/atlas_engine/address_validation/es/query_builder.rb +160 -0
  182. data/app/models/atlas_engine/address_validation/es/term_vectors.rb +78 -0
  183. data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +123 -0
  184. data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +18 -0
  185. data/app/models/atlas_engine/address_validation/es/validators/restriction_evaluator.rb +37 -0
  186. data/app/models/atlas_engine/address_validation/field.rb +30 -0
  187. data/app/models/atlas_engine/address_validation/full_address_validator_base.rb +27 -0
  188. data/app/models/atlas_engine/address_validation/log_emitter.rb +66 -0
  189. data/app/models/atlas_engine/address_validation/matching_strategies.rb +16 -0
  190. data/app/models/atlas_engine/address_validation/normalizer.rb +38 -0
  191. data/app/models/atlas_engine/address_validation/predicate_pipeline.rb +80 -0
  192. data/app/models/atlas_engine/address_validation/request.rb +12 -0
  193. data/app/models/atlas_engine/address_validation/result.rb +154 -0
  194. data/app/models/atlas_engine/address_validation/runs_validation.rb +16 -0
  195. data/app/models/atlas_engine/address_validation/session.rb +47 -0
  196. data/app/models/atlas_engine/address_validation/statsd_emitter.rb +72 -0
  197. data/app/models/atlas_engine/address_validation/strategies.rb +10 -0
  198. data/app/models/atlas_engine/address_validation/suggestion.rb +97 -0
  199. data/app/models/atlas_engine/address_validation/token/comparator.rb +44 -0
  200. data/app/models/atlas_engine/address_validation/token/comparison.rb +76 -0
  201. data/app/models/atlas_engine/address_validation/token/sequence/comparator.rb +158 -0
  202. data/app/models/atlas_engine/address_validation/token/sequence/comparison.rb +166 -0
  203. data/app/models/atlas_engine/address_validation/token/sequence.rb +147 -0
  204. data/app/models/atlas_engine/address_validation/token/synonyms.rb +77 -0
  205. data/app/models/atlas_engine/address_validation/token.rb +113 -0
  206. data/app/models/atlas_engine/address_validation/validator.rb +147 -0
  207. data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +97 -0
  208. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +164 -0
  209. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +46 -0
  210. data/app/models/atlas_engine/address_validation/validators/full_address/comparison_helper.rb +135 -0
  211. data/app/models/atlas_engine/address_validation/validators/full_address/components_to_validate.rb +88 -0
  212. data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +127 -0
  213. data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +23 -0
  214. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +42 -0
  215. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern.rb +37 -0
  216. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern.rb +37 -0
  217. data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +26 -0
  218. data/app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb +31 -0
  219. data/app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb +60 -0
  220. data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +42 -0
  221. data/app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb +140 -0
  222. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern.rb +30 -0
  223. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +38 -0
  224. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb +32 -0
  225. data/app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern.rb +84 -0
  226. data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +22 -0
  227. data/app/models/atlas_engine/address_validation/validators/predicates/cache.rb +38 -0
  228. data/app/models/atlas_engine/address_validation/validators/predicates/city/present.rb +36 -0
  229. data/app/models/atlas_engine/address_validation/validators/predicates/country/exists.rb +34 -0
  230. data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +60 -0
  231. data/app/models/atlas_engine/address_validation/validators/predicates/no_emojis.rb +38 -0
  232. data/app/models/atlas_engine/address_validation/validators/predicates/no_html_tags.rb +39 -0
  233. data/app/models/atlas_engine/address_validation/validators/predicates/no_url.rb +38 -0
  234. data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_length.rb +34 -0
  235. data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_token_count.rb +63 -0
  236. data/app/models/atlas_engine/address_validation/validators/predicates/phone/valid.rb +41 -0
  237. data/app/models/atlas_engine/address_validation/validators/predicates/predicate.rb +37 -0
  238. data/app/models/atlas_engine/address_validation/validators/predicates/province/exists.rb +43 -0
  239. data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +48 -0
  240. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1.rb +45 -0
  241. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +43 -0
  242. data/app/models/atlas_engine/address_validation/validators/predicates/street/present.rb +35 -0
  243. data/app/models/atlas_engine/address_validation/validators/predicates/zip/present.rb +58 -0
  244. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +45 -0
  245. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +55 -0
  246. data/app/models/atlas_engine/address_validation/validators/predicates/zip/zip_base.rb +25 -0
  247. data/app/models/atlas_engine/address_validation/zip_truncator.rb +32 -0
  248. data/app/models/atlas_engine/application_record.rb +8 -0
  249. data/app/models/atlas_engine/coded_error.rb +18 -0
  250. data/app/models/atlas_engine/coded_errors.rb +17 -0
  251. data/app/models/atlas_engine/country_import.rb +44 -0
  252. data/app/models/atlas_engine/country_profile.rb +270 -0
  253. data/app/models/atlas_engine/country_profile_ingestion_subset.rb +42 -0
  254. data/app/models/atlas_engine/country_profile_subset_base.rb +22 -0
  255. data/app/models/atlas_engine/country_profile_validation_subset.rb +48 -0
  256. data/app/models/atlas_engine/country_repository.rb +110 -0
  257. data/app/models/atlas_engine/elasticsearch/client.rb +116 -0
  258. data/app/models/atlas_engine/elasticsearch/client_interface.rb +89 -0
  259. data/app/models/atlas_engine/elasticsearch/repository.rb +246 -0
  260. data/app/models/atlas_engine/elasticsearch/repository_interface.rb +82 -0
  261. data/app/models/atlas_engine/elasticsearch/response.rb +20 -0
  262. data/app/models/atlas_engine/event.rb +12 -0
  263. data/app/models/atlas_engine/field_decompounder.rb +36 -0
  264. data/app/models/atlas_engine/index_configuration_factory.rb +188 -0
  265. data/app/models/atlas_engine/post_address.rb +114 -0
  266. data/app/models/atlas_engine/post_address_importer.rb +34 -0
  267. data/app/models/atlas_engine/services/service_helper.rb +21 -0
  268. data/app/models/atlas_engine/services/validation.rb +65 -0
  269. data/app/models/atlas_engine/services/validation_eligibility.rb +18 -0
  270. data/app/models/atlas_engine/street.rb +34 -0
  271. data/app/tasks/maintenance/atlas_engine/elasticsearch_index_create_task.rb +106 -0
  272. data/app/tasks/maintenance/atlas_engine/geo_json_import_task.rb +29 -0
  273. data/app/views/atlas_engine/connectivity/index.html.erb +50 -0
  274. data/app/views/atlas_engine/country_imports/index.html.erb +49 -0
  275. data/app/views/atlas_engine/country_imports/show.html.erb +73 -0
  276. data/app/views/layouts/atlas_engine/application.html.erb +15 -0
  277. data/config/initializers/1.ruby_patches.rb +18 -0
  278. data/config/initializers/sorbet.rb +5 -0
  279. data/config/initializers/worldwide.rb +5 -0
  280. data/config/locales/internal/en.yml +14 -0
  281. data/config/routes.rb +17 -0
  282. data/db/data/address_synonyms/index_configurations/default.yml +141 -0
  283. data/db/data/country_profiles/default.yml +23 -0
  284. data/db/data/transcriber.yml +760 -0
  285. data/db/data/validation_pipelines/es.yml +58 -0
  286. data/db/data/validation_pipelines/es_street.yml +58 -0
  287. data/db/data/validation_pipelines/local.yml +60 -0
  288. data/db/migrate/20230919173037_create_atlas_engine_post_addresses.rb +25 -0
  289. data/db/migrate/20231117142735_add_building_and_unit_ranges_column.rb +7 -0
  290. data/db/migrate/20231117143536_create_atlas_engine_country_imports.rb +11 -0
  291. data/db/migrate/20231117145844_create_atlas_engine_events_table.rb +13 -0
  292. data/db/migrate/20231123153554_add_unique_index_to_atlas_engine_post_addresses.rb +14 -0
  293. data/db/migrate/20231123154658_add_index_to_post_addresses_on_source_id_locale_country_code.rb +12 -0
  294. data/lib/atlas_engine/engine.rb +10 -0
  295. data/lib/atlas_engine/version.rb +6 -0
  296. data/lib/atlas_engine.rb +66 -0
  297. data/lib/tasks/atlas_engine/address_importer.rake +20 -0
  298. metadata +553 -0
@@ -0,0 +1,270 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ class CountryProfile < FrozenRecord::Base
6
+ extend T::Sig
7
+
8
+ class CountryNotFoundError < StandardError; end
9
+
10
+ module Backend
11
+ extend FrozenRecord::Backends::Yaml
12
+
13
+ class << self
14
+ extend T::Sig
15
+
16
+ sig { params(_file_path: String).returns(T::Array[T.untyped]) }
17
+ def load(_file_path)
18
+ # FrozenRecord's default is to operate on a single YAML file containing all the records.
19
+ # A custom backend like ours, that uses separate files, must load all of them and return an array.
20
+ country_profiles = load_and_merge_fragments(CountryProfile.country_paths)
21
+ locale_profiles = load_and_merge_fragments(CountryProfile.locale_paths)
22
+
23
+ # These hashes are not complete country profiles, but rather fragments that will be merged
24
+ # onto the default profile template.
25
+ country_profiles + localize_profiles(country_profiles, locale_profiles)
26
+ end
27
+
28
+ private
29
+
30
+ sig { params(path_patterns: T::Array[String]).returns(T::Array[T::Hash[String, T.untyped]]) }
31
+ def load_and_merge_fragments(path_patterns)
32
+ path_patterns.flat_map do |directory_pattern|
33
+ Dir[directory_pattern]
34
+ end.map do |profile_path|
35
+ FrozenRecord::Backends::Yaml.load(profile_path)
36
+ end.group_by do |profile|
37
+ profile["id"]
38
+ end.transform_values do |profile_fragments|
39
+ profile_fragments.inject({}) do |memo, fragment|
40
+ memo.deep_merge(fragment)
41
+ end
42
+ end.values
43
+ end
44
+
45
+ sig do
46
+ params(country_profiles: T::Array[T.untyped], locale_profiles: T::Array[T.untyped])
47
+ .returns(T::Array[T.untyped])
48
+ end
49
+ def localize_profiles(country_profiles, locale_profiles)
50
+ locale_profiles.map do |locale_profile|
51
+ base_profile_id = country_id_from_locale_id(locale_profile["id"])
52
+
53
+ base_profile = country_profiles.find do |country_profile|
54
+ country_profile["id"] == base_profile_id
55
+ end
56
+
57
+ (base_profile || {}).deep_merge(locale_profile)
58
+ end
59
+ end
60
+
61
+ sig { params(locale_id: String).returns(String) }
62
+ def country_id_from_locale_id(locale_id)
63
+ unless locale_id.match?(/\A[A-Z]{2}_[A-Z]{2}\z/)
64
+ raise "Invalid id for localized country profile: #{locale_id}"
65
+ end
66
+
67
+ T.must(locale_id.split("_").first)
68
+ end
69
+ end
70
+ end
71
+
72
+ DEFAULT_PROFILE = "DEFAULT"
73
+
74
+ add_index :id, unique: true
75
+ self.base_path = ""
76
+ self.backend = Backend
77
+
78
+ # rubocop:disable Style/ClassVars
79
+ @@default_paths = T.let(
80
+ [
81
+ File.join(AtlasEngine::Engine.root, "db/data/country_profiles/default.yml"),
82
+ ],
83
+ T::Array[String],
84
+ )
85
+
86
+ @@country_paths = T.let(
87
+ [
88
+ File.join(AtlasEngine::Engine.root, "app/countries/atlas_engine/*/country_profile.yml"),
89
+ ],
90
+ T::Array[String],
91
+ )
92
+
93
+ @@locale_paths = T.let(
94
+ [
95
+ File.join(AtlasEngine::Engine.root, "app/countries/atlas_engine/*/locales/*/country_profile.yml"),
96
+ ],
97
+ T::Array[String],
98
+ )
99
+
100
+ @attributes = T.let([], T::Array[T.untyped])
101
+ @records = T.let(nil, T.nilable(T::Array[T.untyped]))
102
+
103
+ class << self
104
+ extend T::Sig
105
+
106
+ sig { returns(T::Array[String]) }
107
+ def default_paths
108
+ @@default_paths
109
+ end
110
+
111
+ sig { params(paths: T::Array[String]).void }
112
+ def default_paths=(paths)
113
+ @@default_paths = paths
114
+ end
115
+
116
+ sig { returns(T::Array[String]) }
117
+ def country_paths
118
+ @@country_paths
119
+ end
120
+
121
+ sig { params(paths: T::Array[String]).void }
122
+ def country_paths=(paths)
123
+ @@country_paths = paths
124
+ end
125
+
126
+ sig { returns(T::Array[String]) }
127
+ def locale_paths
128
+ @@locale_paths
129
+ end
130
+
131
+ sig { params(paths: T::Array[String]).void }
132
+ def locale_paths=(paths)
133
+ @@locale_paths = paths
134
+ end
135
+
136
+ sig { params(paths: T.any(String, T::Array[String])).void }
137
+ def add_default_paths(paths)
138
+ T.unsafe(@@default_paths).append(*Array(paths))
139
+ end
140
+
141
+ sig { params(paths: T.any(String, T::Array[String])).void }
142
+ def add_country_paths(paths)
143
+ T.unsafe(@@country_paths).append(*Array(paths))
144
+ end
145
+
146
+ sig { params(paths: T.any(String, T::Array[String])).void }
147
+ def add_locale_paths(paths)
148
+ T.unsafe(@@locale_paths).append(*Array(paths))
149
+ end
150
+
151
+ sig { void }
152
+ def reset!
153
+ unload!
154
+ @@default_paths = []
155
+ @@country_paths = []
156
+ @@locale_paths = []
157
+ @default_attributes = nil
158
+ end
159
+ # rubocop:enable Style/ClassVars
160
+
161
+ # Overriding (load_records) from FrozenRecord::Base
162
+ # so that we only create attribute methods that are not already defined
163
+ sig { params(force: T::Boolean).returns(T::Array[T.untyped]) }
164
+ def load_records(force: false)
165
+ if force || (auto_reloading && file_changed?)
166
+ unload!
167
+ end
168
+
169
+ @records ||= begin
170
+ records = backend.load(file_path)
171
+ if attribute_deserializers.any? || default_attributes
172
+ records = records.map { |r| assign_defaults!(deserialize_attributes!(r.dup)).freeze }.freeze
173
+ end
174
+ @attributes = list_attributes(records).freeze
175
+ define_attribute_methods(methods_to_be_created)
176
+ records = FrozenRecord.ignore_max_records_scan { records.map { |r| load(r) }.freeze }
177
+ index_definitions.values.each { |index| index.build(records) }
178
+ records
179
+ end
180
+ end
181
+
182
+ sig { params(country_code: String, locale: T.nilable(String)).returns(CountryProfile) }
183
+ def for(country_code, locale = nil)
184
+ raise CountryNotFoundError if country_code.blank?
185
+
186
+ unless country_code == DEFAULT_PROFILE || Worldwide.region(code: country_code).country?
187
+ raise CountryNotFoundError
188
+ end
189
+
190
+ ids = [country_code.upcase]
191
+ ids.push("#{country_code.upcase}_#{locale.upcase}") if locale.present?
192
+
193
+ # if a localized profile is not found, fall back to the
194
+ # country's profile before falling back to the default profile
195
+ begin
196
+ id = ids.pop
197
+ find(id)
198
+ rescue FrozenRecord::RecordNotFound
199
+ if ids.present?
200
+ retry
201
+ else
202
+ new(default_attributes.merge("id" => id))
203
+ end
204
+ end
205
+ end
206
+
207
+ sig { returns(T::Hash[String, T.untyped]) }
208
+ def default_attributes
209
+ @default_attributes ||= T.let(
210
+ default_paths.each_with_object({}) do |path, hash|
211
+ hash.deep_merge!(YAML.load_file(path))
212
+ end,
213
+ T.nilable(T::Hash[String, T.untyped]),
214
+ )
215
+ end
216
+
217
+ sig { override.params(record: T::Hash[String, T.untyped]).returns(T::Hash[String, T.untyped]) }
218
+ def assign_defaults!(record)
219
+ default_attributes.deep_merge(record)
220
+ end
221
+
222
+ sig { returns(T::Set[String]) }
223
+ def partial_zip_allowed_countries
224
+ @partial_zip_allowed_countries ||= T.let(
225
+ where.not(id: DEFAULT_PROFILE).filter do |country_profile|
226
+ country_profile.ingestion.allow_partial_zip?
227
+ end.map(&:id).to_set,
228
+ T.nilable(T::Set[String]),
229
+ )
230
+ end
231
+
232
+ sig { returns(T::Set[String]) }
233
+ def validation_enabled_countries
234
+ @validation_enabled_countries ||= T.let(
235
+ where.not(id: DEFAULT_PROFILE).filter do |country_profile|
236
+ country_profile.validation.enabled
237
+ end.pluck(:id).to_set,
238
+ T.nilable(T::Set[String]),
239
+ )
240
+ end
241
+
242
+ private
243
+
244
+ sig { returns(T::Array[T.untyped]) }
245
+ def methods_to_be_created
246
+ @attributes.to_a.flatten.reject do |attribute_name|
247
+ instance_methods.include?(attribute_name.to_sym)
248
+ end
249
+ end
250
+ end
251
+
252
+ sig { returns(CountryProfileValidationSubset).checked(:tests) }
253
+ def validation
254
+ CountryProfileValidationSubset.new(hash: attributes["validation"] || {})
255
+ end
256
+
257
+ sig { returns(CountryProfileIngestionSubset).checked(:tests) }
258
+ def ingestion
259
+ CountryProfileIngestionSubset.new(hash: attributes["ingestion"])
260
+ end
261
+
262
+ sig { returns(T::Hash[Symbol, T.untyped]) }
263
+ def open_address = (attributes["open_address"] || {}).with_indifferent_access
264
+
265
+ sig { params(field: Symbol).returns(T::Array[String]) }
266
+ def decompounding_patterns(field)
267
+ attributes.dig("decompounding_patterns", field.to_s) || []
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,42 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ class CountryProfileIngestionSubset < CountryProfileSubsetBase
6
+ sig { params(source: String).returns(T::Array[T::Class[T.anything]]) }
7
+ def correctors(source:)
8
+ corrector_names = attributes.dig("correctors", source) || []
9
+ corrector_names.map(&:constantize)
10
+ end
11
+
12
+ sig { returns(T.nilable(String)) }
13
+ def settings_number_of_shards
14
+ attributes.dig("settings", "number_of_shards")
15
+ end
16
+
17
+ sig { returns(T.nilable(String)) }
18
+ def settings_number_of_replicas
19
+ attributes.dig("settings", "number_of_replicas")
20
+ end
21
+
22
+ sig { returns(T.nilable(String)) }
23
+ def settings_min_zip_edge_ngram
24
+ attributes.dig("settings", "min_zip_edge_ngram")
25
+ end
26
+
27
+ sig { returns(T::Class[AddressImporter::OpenAddress::DefaultMapper]) }
28
+ def open_address_feature_mapper
29
+ attributes.dig("open_address", "feature_mapper").constantize
30
+ end
31
+
32
+ sig { returns(T.nilable(String)) }
33
+ def settings_max_zip_edge_ngram
34
+ attributes.dig("settings", "max_zip_edge_ngram")
35
+ end
36
+
37
+ sig { returns(T::Class[AddressValidation::Es::DataMappers::DefaultDataMapper]) }
38
+ def data_mapper
39
+ attributes.dig("data_mapper").constantize
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ class CountryProfileSubsetBase
6
+ extend T::Sig
7
+
8
+ sig { returns(T::Hash[T.untyped, T.untyped]) }
9
+ attr_reader :attributes
10
+
11
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).void }
12
+ def initialize(hash:)
13
+ @attributes = hash
14
+
15
+ attributes.keys.each do |key|
16
+ define_singleton_method(key.to_s) do
17
+ @attributes[key]
18
+ end unless respond_to?(key.to_s)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ class CountryProfileValidationSubset < CountryProfileSubsetBase
6
+ sig { returns(T::Boolean) }
7
+ def enabled
8
+ !!attributes.dig("enabled")
9
+ end
10
+
11
+ sig { returns(T.nilable(String)) }
12
+ def default_matching_strategy
13
+ attributes.dig("default_matching_strategy")
14
+ end
15
+
16
+ sig { returns(T::Array[String]) }
17
+ def index_locales
18
+ attributes.dig("index_locales") || []
19
+ end
20
+
21
+ sig { returns(T::Boolean) }
22
+ def multi_locale?
23
+ index_locales.size > 1
24
+ end
25
+
26
+ sig do
27
+ params(component: String)
28
+ .returns(T::Array[T.class_of(AddressValidation::Validators::FullAddress::Exclusions::ExclusionBase)])
29
+ end
30
+ def validation_exclusions(component:)
31
+ validation_exclusions = attributes.dig("exclusions", component) || []
32
+ validation_exclusions.map(&:constantize)
33
+ end
34
+
35
+ sig { params(length: Integer).returns(T.nilable(T::Range[T.untyped])) }
36
+ def partial_postal_code_range(length)
37
+ range = attributes.dig("partial_postal_code_range_for_length", length)
38
+ return unless range
39
+
40
+ Range.new(*range.split("..").map(&:to_i))
41
+ end
42
+
43
+ sig { returns(T::Class[ValidationTranscriber::AddressParserBase]) }
44
+ def address_parser
45
+ attributes.dig("address_parser").constantize
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,110 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ class CountryRepository
6
+ include LogHelper
7
+ extend T::Sig
8
+
9
+ PostAddressData = T.type_alias { T.any(PostAddress, T::Hash[Symbol, T.untyped]) }
10
+
11
+ delegate :active_alias,
12
+ :archived_alias,
13
+ :new_alias,
14
+ :read_alias_name,
15
+ :record_source,
16
+ :create_next_index,
17
+ :switch_to_next_index,
18
+ :save_records_backfill,
19
+ to: :repository
20
+
21
+ sig do
22
+ params(
23
+ country_code: T.any(String, Symbol),
24
+ repository_class: T::Class[Elasticsearch::RepositoryInterface],
25
+ locale: T.nilable(String),
26
+ index_configuration: T.nilable(IndexConfigurationFactory::IndexConfigurations),
27
+ ).void
28
+ end
29
+ def initialize(country_code:, repository_class:, locale: nil, index_configuration: nil)
30
+ @country_code = T.let(country_code.to_s.downcase, String)
31
+ @country_profile = T.let(CountryProfile.for(@country_code, locale), CountryProfile)
32
+
33
+ @repository = T.let(
34
+ repository_class.new(
35
+ index_base_name: index_name(country_code: @country_code, locale: locale),
36
+ index_mappings: index_configuration.present? ? index_configuration["mappings"] : {},
37
+ index_settings: index_configuration.present? ? index_configuration["settings"] : {},
38
+ mapper_callable: mapper_callable,
39
+ ),
40
+ Elasticsearch::RepositoryInterface,
41
+ )
42
+ end
43
+
44
+ sig { params(id: T.any(String, Integer)).returns(T::Hash[String, T.untyped]) }
45
+ def find(id)
46
+ repository.find(id).deep_stringify_keys
47
+ end
48
+
49
+ sig { params(query: T::Hash[String, T.untyped]).returns(T::Array[T::Hash[String, T.untyped]]) }
50
+ def search(query)
51
+ repository.search(query)["hits"]["hits"]
52
+ end
53
+
54
+ sig { params(query: T::Hash[String, T.untyped]).returns(T::Array[T::Hash[String, T.untyped]]) }
55
+ def analyze(query)
56
+ build_analyze_result(repository.analyze(query))
57
+ end
58
+
59
+ sig { params(query: T::Hash[String, T.untyped]).returns(T::Array[T::Hash[String, T.untyped]]) }
60
+ def term_vectors(query)
61
+ build_term_vectors(repository.term_vectors(query))
62
+ end
63
+
64
+ private
65
+
66
+ sig { params(country_code: T.any(String, Symbol), locale: T.nilable(String)).returns(String) }
67
+ def index_name(country_code:, locale: nil)
68
+ if country_profile.validation.multi_locale?
69
+ if country_profile.validation.index_locales.include?(locale)
70
+ "#{country_code}_#{locale}"
71
+ else
72
+ raise ArgumentError, "#{country_code} is a multi-locale country and requires a locale"
73
+ end
74
+ else
75
+ country_code.to_s.downcase
76
+ end
77
+ end
78
+
79
+ sig { returns(CountryProfile) }
80
+ attr_reader :country_profile
81
+
82
+ sig { returns(Elasticsearch::RepositoryInterface) }
83
+ attr_reader :repository
84
+
85
+ sig { params(es_response: T::Hash[String, T.untyped]).returns(T::Array[T.untyped]) }
86
+ def build_analyze_result(es_response)
87
+ Array(es_response["tokens"])
88
+ end
89
+
90
+ sig { params(es_response: T::Hash[String, T.untyped]).returns(T::Array[T.untyped]) }
91
+ def build_term_vectors(es_response)
92
+ Array(es_response["docs"])
93
+ end
94
+
95
+ sig { returns(T.nilable(T.proc.params(arg0: T.untyped).returns(T.untyped))) }
96
+ def mapper_callable
97
+ # Caching because there's only one per country
98
+ return @mapper_callable if @mapper_callable
99
+
100
+ mapper_class = country_profile.ingestion.data_mapper
101
+
102
+ @mapper_callable = T.let(
103
+ ->(address) {
104
+ mapper_class.new(post_address: address, country_profile:).map_data
105
+ },
106
+ T.nilable(T.proc.params(arg0: T.untyped).returns(T.untyped)),
107
+ )
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,116 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Elasticsearch
6
+ class Client
7
+ extend T::Sig
8
+ include ClientInterface
9
+
10
+ DEFAULT_OPTIONS = T.let(
11
+ {
12
+ read_timeout: 1,
13
+ open_timeout: 1,
14
+ keep_alive_timeout: 60,
15
+ retry_on_failure: false,
16
+ headers: {},
17
+ },
18
+ ConfigType,
19
+ )
20
+
21
+ sig { override.returns(ConfigType) }
22
+ attr_reader :config
23
+
24
+ sig { params(config: ConfigType).void }
25
+ def initialize(config = {})
26
+ @config = T.let(DEFAULT_OPTIONS.merge(config).freeze, ConfigType)
27
+
28
+ options = {
29
+ url: @config[:url] || ENV["ELASTICSEARCH_URL"],
30
+ retry_on_failure: false,
31
+ }.compact
32
+
33
+ @client = T.let(
34
+ Elastic::Transport::Client.new(options) do |faraday_connection|
35
+ faraday_connection.options.timeout = read_timeout
36
+ faraday_connection.options.open_timeout = open_timeout
37
+ @config[:headers][:"Content-Type"] = "application/json"
38
+
39
+ if ENV["ELASTICSEARCH_API_KEY"].present?
40
+ @config[:headers][:Authorization] = "ApiKey #{ENV["ELASTICSEARCH_API_KEY"]}"
41
+ end
42
+ faraday_connection.headers = @config[:headers] if @config[:headers].present?
43
+
44
+ if ENV["ELASTICSEARCH_CLIENT_CERT"] && ENV["ELASTICSEARCH_CLIENT_KEY"]
45
+ faraday_connection.ssl.client_cert = ENV["ELASTICSEARCH_CLIENT_CERT"]
46
+ faraday_connection.ssl.client_key = ENV["ELASTICSEARCH_CLIENT_KEY"]
47
+ faraday_connection.ssl.verify = true
48
+ end
49
+
50
+ if ENV["ELASTICSEARCH_CLIENT_CA_CERT"]
51
+ faraday_connection.ssl.ca_file = ENV["ELASTICSEARCH_CLIENT_CA_CERT"]
52
+ faraday_connection.ssl.verify = true
53
+ end
54
+
55
+ if ENV["ELASTICSEARCH_INSECURE_NO_VERIFY_SERVER"]
56
+ faraday_connection.ssl.verify = false
57
+ end
58
+ end,
59
+ Elastic::Transport::Client,
60
+ )
61
+ end
62
+
63
+ sig do
64
+ override.params(
65
+ method: T.any(Symbol, String),
66
+ path: String,
67
+ body: T.nilable(BodyType),
68
+ options: ConfigType,
69
+ ).returns(AtlasEngine::Elasticsearch::Response)
70
+ end
71
+ def request(method, path, body = nil, options = config.dup)
72
+ raw_request(method, path, body, options)
73
+ end
74
+
75
+ sig { override.params(alias_name: String).returns(T.nilable(String)) }
76
+ def find_index_by(alias_name:)
77
+ get("_alias/#{alias_name}").body.keys.first
78
+ rescue Elastic::Transport::Transport::Errors::NotFound
79
+ nil
80
+ end
81
+
82
+ sig { override.params(name: String).returns(T::Boolean) }
83
+ def index_or_alias_exists?(name)
84
+ head(name).status == 200
85
+ rescue Elastic::Transport::Transport::Errors::NotFound
86
+ false
87
+ end
88
+
89
+ private
90
+
91
+ sig { returns(Integer) }
92
+ def read_timeout
93
+ @config[:read_timeout] # Value is in seconds
94
+ end
95
+
96
+ sig { returns(Integer) }
97
+ def open_timeout
98
+ @config[:open_timeout] # Value is in seconds
99
+ end
100
+
101
+ sig do
102
+ params(
103
+ method: T.any(Symbol, String),
104
+ path: String,
105
+ body: T.nilable(BodyType),
106
+ options: ConfigType,
107
+ ).returns(Response)
108
+ end
109
+ def raw_request(method, path, body, options)
110
+ params = options[:params] ||= {}
111
+ headers = options[:headers] ||= {}
112
+ Response.new(@client.transport.perform_request(method, path, params, body, headers))
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,89 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Elasticsearch
6
+ module ClientInterface
7
+ extend T::Sig
8
+ extend T::Helpers
9
+ abstract!
10
+
11
+ ConfigType = T.type_alias { T::Hash[Symbol, T.untyped] }
12
+ BodyType = T.type_alias { T.any(String, T::Hash[T.untyped, T.untyped]) }
13
+
14
+ sig { abstract.returns(ConfigType) }
15
+ def config; end
16
+
17
+ sig do
18
+ params(
19
+ path: String,
20
+ body: T.nilable(BodyType),
21
+ options: ConfigType,
22
+ ).returns(Response)
23
+ end
24
+ def get(path, body = nil, options = config.dup)
25
+ request(:get, path, nil, options)
26
+ end
27
+
28
+ sig do
29
+ params(
30
+ path: String,
31
+ body: T.nilable(BodyType),
32
+ options: ConfigType,
33
+ ).returns(Response)
34
+ end
35
+ def head(path, body = nil, options = config.dup)
36
+ request(:head, path, body, options)
37
+ end
38
+
39
+ sig do
40
+ params(
41
+ path: String,
42
+ body: T.nilable(BodyType),
43
+ options: ConfigType,
44
+ ).returns(Response)
45
+ end
46
+ def post(path, body = nil, options = config.dup)
47
+ request(:post, path, body, options)
48
+ end
49
+
50
+ sig do
51
+ params(
52
+ path: String,
53
+ body: T.nilable(BodyType),
54
+ options: ConfigType,
55
+ ).returns(Response)
56
+ end
57
+ def put(path, body = nil, options = config.dup)
58
+ request(:put, path, body, options)
59
+ end
60
+
61
+ sig do
62
+ params(
63
+ path: String,
64
+ body: T.nilable(BodyType),
65
+ options: ConfigType,
66
+ ).returns(Response)
67
+ end
68
+ def delete(path, body = nil, options = config.dup)
69
+ request(:delete, path, body, options)
70
+ end
71
+
72
+ sig do
73
+ abstract.params(
74
+ method: T.any(Symbol, String),
75
+ path: String,
76
+ body: T.nilable(BodyType),
77
+ options: T::Hash[Symbol, T.untyped],
78
+ ).returns(Response)
79
+ end
80
+ def request(method, path, body = nil, options = {}); end
81
+
82
+ sig { abstract.params(alias_name: String).returns(T.nilable(String)) }
83
+ def find_index_by(alias_name:); end
84
+
85
+ sig { abstract.params(name: String).returns(T::Boolean) }
86
+ def index_or_alias_exists?(name); end
87
+ end
88
+ end
89
+ end