e-invoice-api 0.1.0.pre.alpha.5

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 (233) hide show
  1. checksums.yaml +7 -0
  2. data/.ignore +2 -0
  3. data/CHANGELOG.md +57 -0
  4. data/README.md +285 -0
  5. data/SECURITY.md +27 -0
  6. data/lib/e_invoice_api/client.rb +94 -0
  7. data/lib/e_invoice_api/errors.rb +192 -0
  8. data/lib/e_invoice_api/file_part.rb +55 -0
  9. data/lib/e_invoice_api/internal/documents_number_page.rb +96 -0
  10. data/lib/e_invoice_api/internal/transport/base_client.rb +555 -0
  11. data/lib/e_invoice_api/internal/transport/pooled_net_requester.rb +209 -0
  12. data/lib/e_invoice_api/internal/type/array_of.rb +162 -0
  13. data/lib/e_invoice_api/internal/type/base_model.rb +482 -0
  14. data/lib/e_invoice_api/internal/type/base_page.rb +55 -0
  15. data/lib/e_invoice_api/internal/type/boolean.rb +71 -0
  16. data/lib/e_invoice_api/internal/type/converter.rb +292 -0
  17. data/lib/e_invoice_api/internal/type/enum.rb +148 -0
  18. data/lib/e_invoice_api/internal/type/file_input.rb +103 -0
  19. data/lib/e_invoice_api/internal/type/hash_of.rb +182 -0
  20. data/lib/e_invoice_api/internal/type/request_parameters.rb +42 -0
  21. data/lib/e_invoice_api/internal/type/union.rb +236 -0
  22. data/lib/e_invoice_api/internal/type/unknown.rb +75 -0
  23. data/lib/e_invoice_api/internal/util.rb +914 -0
  24. data/lib/e_invoice_api/internal.rb +20 -0
  25. data/lib/e_invoice_api/models/certificate.rb +34 -0
  26. data/lib/e_invoice_api/models/currency_code.rb +28 -0
  27. data/lib/e_invoice_api/models/document_attachment_create.rb +33 -0
  28. data/lib/e_invoice_api/models/document_create.rb +521 -0
  29. data/lib/e_invoice_api/models/document_create_params.rb +14 -0
  30. data/lib/e_invoice_api/models/document_delete_params.rb +14 -0
  31. data/lib/e_invoice_api/models/document_delete_response.rb +16 -0
  32. data/lib/e_invoice_api/models/document_direction.rb +15 -0
  33. data/lib/e_invoice_api/models/document_response.rb +418 -0
  34. data/lib/e_invoice_api/models/document_retrieve_params.rb +14 -0
  35. data/lib/e_invoice_api/models/document_send_params.rb +44 -0
  36. data/lib/e_invoice_api/models/document_state.rb +18 -0
  37. data/lib/e_invoice_api/models/document_type.rb +15 -0
  38. data/lib/e_invoice_api/models/documents/attachment_add_params.rb +22 -0
  39. data/lib/e_invoice_api/models/documents/attachment_delete_params.rb +22 -0
  40. data/lib/e_invoice_api/models/documents/attachment_delete_response.rb +18 -0
  41. data/lib/e_invoice_api/models/documents/attachment_list_params.rb +16 -0
  42. data/lib/e_invoice_api/models/documents/attachment_list_response.rb +11 -0
  43. data/lib/e_invoice_api/models/documents/attachment_retrieve_params.rb +22 -0
  44. data/lib/e_invoice_api/models/documents/document_attachment.rb +44 -0
  45. data/lib/e_invoice_api/models/documents/ubl_get_params.rb +16 -0
  46. data/lib/e_invoice_api/models/documents/ubl_get_response.rb +72 -0
  47. data/lib/e_invoice_api/models/inbox_list_credit_notes_params.rb +30 -0
  48. data/lib/e_invoice_api/models/inbox_list_invoices_params.rb +30 -0
  49. data/lib/e_invoice_api/models/inbox_list_params.rb +78 -0
  50. data/lib/e_invoice_api/models/lookup_retrieve_params.rb +26 -0
  51. data/lib/e_invoice_api/models/lookup_retrieve_response.rb +491 -0
  52. data/lib/e_invoice_api/models/outbox_list_draft_documents_params.rb +30 -0
  53. data/lib/e_invoice_api/models/outbox_list_received_documents_params.rb +78 -0
  54. data/lib/e_invoice_api/models/paginated_document_response.rb +39 -0
  55. data/lib/e_invoice_api/models/payment_detail_create.rb +33 -0
  56. data/lib/e_invoice_api/models/ubl_document_validation.rb +97 -0
  57. data/lib/e_invoice_api/models/unit_of_measure_code.rb +104 -0
  58. data/lib/e_invoice_api/models/validate_validate_json_params.rb +14 -0
  59. data/lib/e_invoice_api/models/validate_validate_peppol_id_params.rb +26 -0
  60. data/lib/e_invoice_api/models/validate_validate_peppol_id_response.rb +80 -0
  61. data/lib/e_invoice_api/models/validate_validate_ubl_params.rb +20 -0
  62. data/lib/e_invoice_api/models/webhook_create_params.rb +32 -0
  63. data/lib/e_invoice_api/models/webhook_delete_params.rb +14 -0
  64. data/lib/e_invoice_api/models/webhook_delete_response.rb +18 -0
  65. data/lib/e_invoice_api/models/webhook_list_params.rb +14 -0
  66. data/lib/e_invoice_api/models/webhook_list_response.rb +8 -0
  67. data/lib/e_invoice_api/models/webhook_response.rb +42 -0
  68. data/lib/e_invoice_api/models/webhook_retrieve_params.rb +14 -0
  69. data/lib/e_invoice_api/models/webhook_update_params.rb +32 -0
  70. data/lib/e_invoice_api/models.rb +105 -0
  71. data/lib/e_invoice_api/request_options.rb +77 -0
  72. data/lib/e_invoice_api/resources/documents/attachments.rb +109 -0
  73. data/lib/e_invoice_api/resources/documents/ubl.rb +35 -0
  74. data/lib/e_invoice_api/resources/documents.rb +188 -0
  75. data/lib/e_invoice_api/resources/inbox.rb +101 -0
  76. data/lib/e_invoice_api/resources/lookup.rb +43 -0
  77. data/lib/e_invoice_api/resources/outbox.rb +76 -0
  78. data/lib/e_invoice_api/resources/validate.rb +168 -0
  79. data/lib/e_invoice_api/resources/webhooks.rb +117 -0
  80. data/lib/e_invoice_api/version.rb +5 -0
  81. data/lib/e_invoice_api.rb +107 -0
  82. data/manifest.yaml +15 -0
  83. data/rbi/e_invoice_api/client.rbi +64 -0
  84. data/rbi/e_invoice_api/errors.rbi +162 -0
  85. data/rbi/e_invoice_api/file_part.rbi +37 -0
  86. data/rbi/e_invoice_api/internal/documents_number_page.rbi +28 -0
  87. data/rbi/e_invoice_api/internal/transport/base_client.rbi +298 -0
  88. data/rbi/e_invoice_api/internal/transport/pooled_net_requester.rbi +80 -0
  89. data/rbi/e_invoice_api/internal/type/array_of.rbi +104 -0
  90. data/rbi/e_invoice_api/internal/type/base_model.rbi +304 -0
  91. data/rbi/e_invoice_api/internal/type/base_page.rbi +43 -0
  92. data/rbi/e_invoice_api/internal/type/boolean.rbi +56 -0
  93. data/rbi/e_invoice_api/internal/type/converter.rbi +162 -0
  94. data/rbi/e_invoice_api/internal/type/enum.rbi +82 -0
  95. data/rbi/e_invoice_api/internal/type/file_input.rbi +59 -0
  96. data/rbi/e_invoice_api/internal/type/hash_of.rbi +104 -0
  97. data/rbi/e_invoice_api/internal/type/request_parameters.rbi +31 -0
  98. data/rbi/e_invoice_api/internal/type/union.rbi +116 -0
  99. data/rbi/e_invoice_api/internal/type/unknown.rbi +56 -0
  100. data/rbi/e_invoice_api/internal/util.rbi +487 -0
  101. data/rbi/e_invoice_api/internal.rbi +18 -0
  102. data/rbi/e_invoice_api/models/certificate.rbi +54 -0
  103. data/rbi/e_invoice_api/models/currency_code.rbi +34 -0
  104. data/rbi/e_invoice_api/models/document_attachment_create.rbi +57 -0
  105. data/rbi/e_invoice_api/models/document_create.rbi +638 -0
  106. data/rbi/e_invoice_api/models/document_create_params.rbi +30 -0
  107. data/rbi/e_invoice_api/models/document_delete_params.rbi +30 -0
  108. data/rbi/e_invoice_api/models/document_delete_response.rbi +26 -0
  109. data/rbi/e_invoice_api/models/document_direction.rbi +22 -0
  110. data/rbi/e_invoice_api/models/document_response.rbi +504 -0
  111. data/rbi/e_invoice_api/models/document_retrieve_params.rbi +30 -0
  112. data/rbi/e_invoice_api/models/document_send_params.rbi +65 -0
  113. data/rbi/e_invoice_api/models/document_state.rbi +24 -0
  114. data/rbi/e_invoice_api/models/document_type.rbi +21 -0
  115. data/rbi/e_invoice_api/models/documents/attachment_add_params.rbi +43 -0
  116. data/rbi/e_invoice_api/models/documents/attachment_delete_params.rbi +43 -0
  117. data/rbi/e_invoice_api/models/documents/attachment_delete_response.rbi +28 -0
  118. data/rbi/e_invoice_api/models/documents/attachment_list_params.rbi +34 -0
  119. data/rbi/e_invoice_api/models/documents/attachment_list_response.rbi +15 -0
  120. data/rbi/e_invoice_api/models/documents/attachment_retrieve_params.rbi +43 -0
  121. data/rbi/e_invoice_api/models/documents/document_attachment.rbi +72 -0
  122. data/rbi/e_invoice_api/models/documents/ubl_get_params.rbi +34 -0
  123. data/rbi/e_invoice_api/models/documents/ubl_get_response.rbi +97 -0
  124. data/rbi/e_invoice_api/models/inbox_list_credit_notes_params.rbi +60 -0
  125. data/rbi/e_invoice_api/models/inbox_list_invoices_params.rbi +60 -0
  126. data/rbi/e_invoice_api/models/inbox_list_params.rbi +105 -0
  127. data/rbi/e_invoice_api/models/lookup_retrieve_params.rbi +45 -0
  128. data/rbi/e_invoice_api/models/lookup_retrieve_response.rbi +852 -0
  129. data/rbi/e_invoice_api/models/outbox_list_draft_documents_params.rbi +60 -0
  130. data/rbi/e_invoice_api/models/outbox_list_received_documents_params.rbi +108 -0
  131. data/rbi/e_invoice_api/models/paginated_document_response.rbi +56 -0
  132. data/rbi/e_invoice_api/models/payment_detail_create.rbi +56 -0
  133. data/rbi/e_invoice_api/models/ubl_document_validation.rbi +159 -0
  134. data/rbi/e_invoice_api/models/unit_of_measure_code.rbi +149 -0
  135. data/rbi/e_invoice_api/models/validate_validate_json_params.rbi +30 -0
  136. data/rbi/e_invoice_api/models/validate_validate_peppol_id_params.rbi +45 -0
  137. data/rbi/e_invoice_api/models/validate_validate_peppol_id_response.rbi +141 -0
  138. data/rbi/e_invoice_api/models/validate_validate_ubl_params.rbi +41 -0
  139. data/rbi/e_invoice_api/models/webhook_create_params.rbi +54 -0
  140. data/rbi/e_invoice_api/models/webhook_delete_params.rbi +30 -0
  141. data/rbi/e_invoice_api/models/webhook_delete_response.rbi +27 -0
  142. data/rbi/e_invoice_api/models/webhook_list_params.rbi +27 -0
  143. data/rbi/e_invoice_api/models/webhook_list_response.rbi +11 -0
  144. data/rbi/e_invoice_api/models/webhook_response.rbi +57 -0
  145. data/rbi/e_invoice_api/models/webhook_retrieve_params.rbi +30 -0
  146. data/rbi/e_invoice_api/models/webhook_update_params.rbi +51 -0
  147. data/rbi/e_invoice_api/models.rbi +70 -0
  148. data/rbi/e_invoice_api/request_options.rbi +59 -0
  149. data/rbi/e_invoice_api/resources/documents/attachments.rbi +58 -0
  150. data/rbi/e_invoice_api/resources/documents/ubl.rbi +24 -0
  151. data/rbi/e_invoice_api/resources/documents.rbi +164 -0
  152. data/rbi/e_invoice_api/resources/inbox.rbi +93 -0
  153. data/rbi/e_invoice_api/resources/lookup.rbi +31 -0
  154. data/rbi/e_invoice_api/resources/outbox.rbi +72 -0
  155. data/rbi/e_invoice_api/resources/validate.rbi +145 -0
  156. data/rbi/e_invoice_api/resources/webhooks.rbi +72 -0
  157. data/rbi/e_invoice_api/version.rbi +5 -0
  158. data/sig/e_invoice_api/client.rbs +36 -0
  159. data/sig/e_invoice_api/errors.rbs +101 -0
  160. data/sig/e_invoice_api/file_part.rbs +21 -0
  161. data/sig/e_invoice_api/internal/documents_number_page.rbs +17 -0
  162. data/sig/e_invoice_api/internal/transport/base_client.rbs +131 -0
  163. data/sig/e_invoice_api/internal/transport/pooled_net_requester.rbs +45 -0
  164. data/sig/e_invoice_api/internal/type/array_of.rbs +48 -0
  165. data/sig/e_invoice_api/internal/type/base_model.rbs +102 -0
  166. data/sig/e_invoice_api/internal/type/base_page.rbs +24 -0
  167. data/sig/e_invoice_api/internal/type/boolean.rbs +26 -0
  168. data/sig/e_invoice_api/internal/type/converter.rbs +56 -0
  169. data/sig/e_invoice_api/internal/type/enum.rbs +32 -0
  170. data/sig/e_invoice_api/internal/type/file_input.rbs +25 -0
  171. data/sig/e_invoice_api/internal/type/hash_of.rbs +48 -0
  172. data/sig/e_invoice_api/internal/type/request_parameters.rbs +19 -0
  173. data/sig/e_invoice_api/internal/type/union.rbs +52 -0
  174. data/sig/e_invoice_api/internal/type/unknown.rbs +26 -0
  175. data/sig/e_invoice_api/internal/util.rbs +185 -0
  176. data/sig/e_invoice_api/internal.rbs +9 -0
  177. data/sig/e_invoice_api/models/certificate.rbs +26 -0
  178. data/sig/e_invoice_api/models/currency_code.rbs +42 -0
  179. data/sig/e_invoice_api/models/document_attachment_create.rbs +39 -0
  180. data/sig/e_invoice_api/models/document_create.rbs +403 -0
  181. data/sig/e_invoice_api/models/document_create_params.rbs +15 -0
  182. data/sig/e_invoice_api/models/document_delete_params.rbs +15 -0
  183. data/sig/e_invoice_api/models/document_delete_response.rbs +13 -0
  184. data/sig/e_invoice_api/models/document_direction.rbs +14 -0
  185. data/sig/e_invoice_api/models/document_response.rbs +358 -0
  186. data/sig/e_invoice_api/models/document_retrieve_params.rbs +15 -0
  187. data/sig/e_invoice_api/models/document_send_params.rbs +46 -0
  188. data/sig/e_invoice_api/models/document_state.rbs +17 -0
  189. data/sig/e_invoice_api/models/document_type.rbs +14 -0
  190. data/sig/e_invoice_api/models/documents/attachment_add_params.rbs +26 -0
  191. data/sig/e_invoice_api/models/documents/attachment_delete_params.rbs +26 -0
  192. data/sig/e_invoice_api/models/documents/attachment_delete_response.rbs +15 -0
  193. data/sig/e_invoice_api/models/documents/attachment_list_params.rbs +17 -0
  194. data/sig/e_invoice_api/models/documents/attachment_list_response.rbs +10 -0
  195. data/sig/e_invoice_api/models/documents/attachment_retrieve_params.rbs +26 -0
  196. data/sig/e_invoice_api/models/documents/document_attachment.rbs +48 -0
  197. data/sig/e_invoice_api/models/documents/ubl_get_params.rbs +17 -0
  198. data/sig/e_invoice_api/models/documents/ubl_get_response.rbs +69 -0
  199. data/sig/e_invoice_api/models/inbox_list_credit_notes_params.rbs +32 -0
  200. data/sig/e_invoice_api/models/inbox_list_invoices_params.rbs +32 -0
  201. data/sig/e_invoice_api/models/inbox_list_params.rbs +65 -0
  202. data/sig/e_invoice_api/models/lookup_retrieve_params.rbs +23 -0
  203. data/sig/e_invoice_api/models/lookup_retrieve_response.rbs +365 -0
  204. data/sig/e_invoice_api/models/outbox_list_draft_documents_params.rbs +32 -0
  205. data/sig/e_invoice_api/models/outbox_list_received_documents_params.rbs +65 -0
  206. data/sig/e_invoice_api/models/paginated_document_response.rbs +40 -0
  207. data/sig/e_invoice_api/models/payment_detail_create.rbs +35 -0
  208. data/sig/e_invoice_api/models/ubl_document_validation.rbs +98 -0
  209. data/sig/e_invoice_api/models/unit_of_measure_code.rbs +192 -0
  210. data/sig/e_invoice_api/models/validate_validate_json_params.rbs +15 -0
  211. data/sig/e_invoice_api/models/validate_validate_peppol_id_params.rbs +23 -0
  212. data/sig/e_invoice_api/models/validate_validate_peppol_id_response.rbs +65 -0
  213. data/sig/e_invoice_api/models/validate_validate_ubl_params.rbs +24 -0
  214. data/sig/e_invoice_api/models/webhook_create_params.rbs +34 -0
  215. data/sig/e_invoice_api/models/webhook_delete_params.rbs +15 -0
  216. data/sig/e_invoice_api/models/webhook_delete_response.rbs +13 -0
  217. data/sig/e_invoice_api/models/webhook_list_params.rbs +15 -0
  218. data/sig/e_invoice_api/models/webhook_list_response.rbs +7 -0
  219. data/sig/e_invoice_api/models/webhook_response.rbs +42 -0
  220. data/sig/e_invoice_api/models/webhook_retrieve_params.rbs +15 -0
  221. data/sig/e_invoice_api/models/webhook_update_params.rbs +32 -0
  222. data/sig/e_invoice_api/models.rbs +65 -0
  223. data/sig/e_invoice_api/request_options.rbs +36 -0
  224. data/sig/e_invoice_api/resources/documents/attachments.rbs +32 -0
  225. data/sig/e_invoice_api/resources/documents/ubl.rbs +14 -0
  226. data/sig/e_invoice_api/resources/documents.rbs +76 -0
  227. data/sig/e_invoice_api/resources/inbox.rbs +31 -0
  228. data/sig/e_invoice_api/resources/lookup.rbs +12 -0
  229. data/sig/e_invoice_api/resources/outbox.rbs +25 -0
  230. data/sig/e_invoice_api/resources/validate.rbs +62 -0
  231. data/sig/e_invoice_api/resources/webhooks.rbs +36 -0
  232. data/sig/e_invoice_api/version.rbs +3 -0
  233. metadata +290 -0
@@ -0,0 +1,914 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EInvoiceAPI
4
+ module Internal
5
+ # @api private
6
+ module Util
7
+ # @api private
8
+ #
9
+ # @return [Float]
10
+ def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
11
+
12
+ # @api private
13
+ #
14
+ # @param ns [Module, Class]
15
+ #
16
+ # @return [Enumerable<Module, Class>]
17
+ def self.walk_namespaces(ns)
18
+ ns.constants(false).lazy.flat_map do
19
+ case (c = ns.const_get(_1, false))
20
+ in Module | Class
21
+ walk_namespaces(c)
22
+ else
23
+ []
24
+ end
25
+ end
26
+ .chain([ns])
27
+ end
28
+
29
+ class << self
30
+ # @api private
31
+ #
32
+ # @return [String]
33
+ def arch
34
+ case (arch = RbConfig::CONFIG["arch"])&.downcase
35
+ in nil
36
+ "unknown"
37
+ in /aarch64|arm64/
38
+ "arm64"
39
+ in /x86_64/
40
+ "x64"
41
+ in /arm/
42
+ "arm"
43
+ else
44
+ "other:#{arch}"
45
+ end
46
+ end
47
+
48
+ # @api private
49
+ #
50
+ # @return [String]
51
+ def os
52
+ case (host = RbConfig::CONFIG["host_os"])&.downcase
53
+ in nil
54
+ "Unknown"
55
+ in /linux/
56
+ "Linux"
57
+ in /darwin/
58
+ "MacOS"
59
+ in /freebsd/
60
+ "FreeBSD"
61
+ in /openbsd/
62
+ "OpenBSD"
63
+ in /mswin|mingw|cygwin|ucrt/
64
+ "Windows"
65
+ else
66
+ "Other:#{host}"
67
+ end
68
+ end
69
+ end
70
+
71
+ class << self
72
+ # @api private
73
+ #
74
+ # @param input [Object]
75
+ #
76
+ # @return [Boolean]
77
+ def primitive?(input)
78
+ case input
79
+ in true | false | Numeric | Symbol | String
80
+ true
81
+ else
82
+ false
83
+ end
84
+ end
85
+
86
+ # @api private
87
+ #
88
+ # @param input [String, Boolean]
89
+ #
90
+ # @return [Boolean, Object]
91
+ def coerce_boolean(input)
92
+ case input.is_a?(String) ? input.downcase : input
93
+ in "true"
94
+ true
95
+ in "false"
96
+ false
97
+ else
98
+ input
99
+ end
100
+ end
101
+
102
+ # @api private
103
+ #
104
+ # @param input [String, Boolean]
105
+ #
106
+ # @raise [ArgumentError]
107
+ # @return [Boolean, nil]
108
+ def coerce_boolean!(input)
109
+ case coerce_boolean(input)
110
+ in true | false | nil => coerced
111
+ coerced
112
+ else
113
+ raise ArgumentError.new("Unable to coerce #{input.inspect} into boolean value")
114
+ end
115
+ end
116
+
117
+ # @api private
118
+ #
119
+ # @param input [String, Integer]
120
+ #
121
+ # @return [Integer, Object]
122
+ def coerce_integer(input)
123
+ Integer(input, exception: false) || input
124
+ end
125
+
126
+ # @api private
127
+ #
128
+ # @param input [String, Integer, Float]
129
+ #
130
+ # @return [Float, Object]
131
+ def coerce_float(input)
132
+ Float(input, exception: false) || input
133
+ end
134
+
135
+ # @api private
136
+ #
137
+ # @param input [Object]
138
+ #
139
+ # @return [Hash{Object=>Object}, Object]
140
+ def coerce_hash(input)
141
+ case input
142
+ in NilClass | Array | Set | Enumerator | StringIO | IO
143
+ input
144
+ else
145
+ input.respond_to?(:to_h) ? input.to_h : input
146
+ end
147
+ end
148
+
149
+ # @api private
150
+ #
151
+ # @param input [Object]
152
+ #
153
+ # @raise [ArgumentError]
154
+ # @return [Hash{Object=>Object}, nil]
155
+ def coerce_hash!(input)
156
+ case coerce_hash(input)
157
+ in Hash | nil => coerced
158
+ coerced
159
+ else
160
+ message = "Expected a #{Hash} or #{EInvoiceAPI::Internal::Type::BaseModel}, got #{data.inspect}"
161
+ raise ArgumentError.new(message)
162
+ end
163
+ end
164
+ end
165
+
166
+ class << self
167
+ # @api private
168
+ #
169
+ # @param lhs [Object]
170
+ # @param rhs [Object]
171
+ # @param concat [Boolean]
172
+ #
173
+ # @return [Object]
174
+ private def deep_merge_lr(lhs, rhs, concat: false)
175
+ case [lhs, rhs, concat]
176
+ in [Hash, Hash, _]
177
+ lhs.merge(rhs) { deep_merge_lr(_2, _3, concat: concat) }
178
+ in [Array, Array, true]
179
+ lhs.concat(rhs)
180
+ else
181
+ rhs
182
+ end
183
+ end
184
+
185
+ # @api private
186
+ #
187
+ # Recursively merge one hash with another. If the values at a given key are not
188
+ # both hashes, just take the new value.
189
+ #
190
+ # @param values [Array<Object>]
191
+ #
192
+ # @param sentinel [Object, nil] the value to return if no values are provided.
193
+ #
194
+ # @param concat [Boolean] whether to merge sequences by concatenation.
195
+ #
196
+ # @return [Object]
197
+ def deep_merge(*values, sentinel: nil, concat: false)
198
+ case values
199
+ in [value, *values]
200
+ values.reduce(value) do |acc, val|
201
+ deep_merge_lr(acc, val, concat: concat)
202
+ end
203
+ else
204
+ sentinel
205
+ end
206
+ end
207
+
208
+ # @api private
209
+ #
210
+ # @param data [Hash{Symbol=>Object}, Array<Object>, Object]
211
+ # @param pick [Symbol, Integer, Array<Symbol, Integer>, Proc, nil]
212
+ # @param blk [Proc, nil]
213
+ #
214
+ # @return [Object, nil]
215
+ def dig(data, pick, &blk)
216
+ case [data, pick]
217
+ in [_, nil]
218
+ data
219
+ in [Hash, Symbol] | [Array, Integer]
220
+ data.fetch(pick) { blk&.call }
221
+ in [Hash | Array, Array]
222
+ pick.reduce(data) do |acc, key|
223
+ case acc
224
+ in Hash if acc.key?(key)
225
+ acc.fetch(key)
226
+ in Array if key.is_a?(Integer) && key < acc.length
227
+ acc[key]
228
+ else
229
+ return blk&.call
230
+ end
231
+ end
232
+ in [_, Proc]
233
+ pick.call(data)
234
+ else
235
+ blk&.call
236
+ end
237
+ end
238
+ end
239
+
240
+ class << self
241
+ # @api private
242
+ #
243
+ # @param uri [URI::Generic]
244
+ #
245
+ # @return [String]
246
+ def uri_origin(uri)
247
+ "#{uri.scheme}://#{uri.host}#{uri.port == uri.default_port ? '' : ":#{uri.port}"}"
248
+ end
249
+
250
+ # @api private
251
+ #
252
+ # @param path [String, Array<String>]
253
+ #
254
+ # @return [String]
255
+ def interpolate_path(path)
256
+ case path
257
+ in String
258
+ path
259
+ in []
260
+ ""
261
+ in [String => p, *interpolations]
262
+ encoded = interpolations.map { ERB::Util.url_encode(_1) }
263
+ format(p, *encoded)
264
+ end
265
+ end
266
+ end
267
+
268
+ class << self
269
+ # @api private
270
+ #
271
+ # @param query [String, nil]
272
+ #
273
+ # @return [Hash{String=>Array<String>}]
274
+ def decode_query(query)
275
+ CGI.parse(query.to_s)
276
+ end
277
+
278
+ # @api private
279
+ #
280
+ # @param query [Hash{String=>Array<String>, String, nil}, nil]
281
+ #
282
+ # @return [String, nil]
283
+ def encode_query(query)
284
+ query.to_h.empty? ? nil : URI.encode_www_form(query)
285
+ end
286
+ end
287
+
288
+ class << self
289
+ # @api private
290
+ #
291
+ # @param url [URI::Generic, String]
292
+ #
293
+ # @return [Hash{Symbol=>String, Integer, nil}]
294
+ def parse_uri(url)
295
+ parsed = URI::Generic.component.zip(URI.split(url)).to_h
296
+ {**parsed, query: decode_query(parsed.fetch(:query))}
297
+ end
298
+
299
+ # @api private
300
+ #
301
+ # @param parsed [Hash{Symbol=>String, Integer, nil}] .
302
+ #
303
+ # @option parsed [String, nil] :scheme
304
+ #
305
+ # @option parsed [String, nil] :host
306
+ #
307
+ # @option parsed [Integer, nil] :port
308
+ #
309
+ # @option parsed [String, nil] :path
310
+ #
311
+ # @option parsed [Hash{String=>Array<String>}] :query
312
+ #
313
+ # @return [URI::Generic]
314
+ def unparse_uri(parsed)
315
+ URI::Generic.build(**parsed, query: encode_query(parsed.fetch(:query)))
316
+ end
317
+
318
+ # @api private
319
+ #
320
+ # @param lhs [Hash{Symbol=>String, Integer, nil}] .
321
+ #
322
+ # @option lhs [String, nil] :scheme
323
+ #
324
+ # @option lhs [String, nil] :host
325
+ #
326
+ # @option lhs [Integer, nil] :port
327
+ #
328
+ # @option lhs [String, nil] :path
329
+ #
330
+ # @option lhs [Hash{String=>Array<String>}] :query
331
+ #
332
+ # @param rhs [Hash{Symbol=>String, Integer, nil}] .
333
+ #
334
+ # @option rhs [String, nil] :scheme
335
+ #
336
+ # @option rhs [String, nil] :host
337
+ #
338
+ # @option rhs [Integer, nil] :port
339
+ #
340
+ # @option rhs [String, nil] :path
341
+ #
342
+ # @option rhs [Hash{String=>Array<String>}] :query
343
+ #
344
+ # @return [URI::Generic]
345
+ def join_parsed_uri(lhs, rhs)
346
+ base_path, base_query = lhs.fetch_values(:path, :query)
347
+ slashed = base_path.end_with?("/") ? base_path : "#{base_path}/"
348
+
349
+ parsed_path, parsed_query = parse_uri(rhs.fetch(:path)).fetch_values(:path, :query)
350
+ override = URI::Generic.build(**rhs.slice(:scheme, :host, :port), path: parsed_path)
351
+
352
+ joined = URI.join(URI::Generic.build(lhs.except(:path, :query)), slashed, override)
353
+ query = deep_merge(
354
+ joined.path == base_path ? base_query : {},
355
+ parsed_query,
356
+ rhs[:query].to_h,
357
+ concat: true
358
+ )
359
+
360
+ joined.query = encode_query(query)
361
+ joined
362
+ end
363
+ end
364
+
365
+ class << self
366
+ # @api private
367
+ #
368
+ # @param headers [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}]
369
+ #
370
+ # @return [Hash{String=>String}]
371
+ def normalized_headers(*headers)
372
+ {}.merge(*headers.compact).to_h do |key, val|
373
+ value =
374
+ case val
375
+ in Array
376
+ val.filter_map { _1&.to_s&.strip }.join(", ")
377
+ else
378
+ val&.to_s&.strip
379
+ end
380
+ [key.downcase, value]
381
+ end
382
+ end
383
+ end
384
+
385
+ # @api private
386
+ #
387
+ # An adapter that satisfies the IO interface required by `::IO.copy_stream`
388
+ class ReadIOAdapter
389
+ # @api private
390
+ #
391
+ # @return [Boolean, nil]
392
+ def close? = @closing
393
+
394
+ # @api private
395
+ def close
396
+ case @stream
397
+ in Enumerator
398
+ EInvoiceAPI::Internal::Util.close_fused!(@stream)
399
+ in IO if close?
400
+ @stream.close
401
+ else
402
+ end
403
+ end
404
+
405
+ # @api private
406
+ #
407
+ # @param max_len [Integer, nil]
408
+ #
409
+ # @return [String]
410
+ private def read_enum(max_len)
411
+ case max_len
412
+ in nil
413
+ @stream.to_a.join
414
+ in Integer
415
+ @buf << @stream.next while @buf.length < max_len
416
+ @buf.slice!(..max_len)
417
+ end
418
+ rescue StopIteration
419
+ @stream = nil
420
+ @buf.slice!(0..)
421
+ end
422
+
423
+ # @api private
424
+ #
425
+ # @param max_len [Integer, nil]
426
+ # @param out_string [String, nil]
427
+ #
428
+ # @return [String, nil]
429
+ def read(max_len = nil, out_string = nil)
430
+ case @stream
431
+ in nil
432
+ nil
433
+ in IO | StringIO
434
+ @stream.read(max_len, out_string)
435
+ in Enumerator
436
+ read = read_enum(max_len)
437
+ case out_string
438
+ in String
439
+ out_string.replace(read)
440
+ in nil
441
+ read
442
+ end
443
+ end
444
+ .tap(&@blk)
445
+ end
446
+
447
+ # @api private
448
+ #
449
+ # @param src [String, Pathname, StringIO, Enumerable<String>]
450
+ # @param blk [Proc]
451
+ #
452
+ # @yieldparam [String]
453
+ def initialize(src, &blk)
454
+ @stream =
455
+ case src
456
+ in String
457
+ StringIO.new(src)
458
+ in Pathname
459
+ @closing = true
460
+ src.open(binmode: true)
461
+ else
462
+ src
463
+ end
464
+ @buf = String.new
465
+ @blk = blk
466
+ end
467
+ end
468
+
469
+ class << self
470
+ # @param blk [Proc]
471
+ #
472
+ # @yieldparam [Enumerator::Yielder]
473
+ # @return [Enumerable<String>]
474
+ def writable_enum(&blk)
475
+ Enumerator.new do |y|
476
+ buf = String.new
477
+ y.define_singleton_method(:write) do
478
+ self << buf.replace(_1)
479
+ buf.bytesize
480
+ end
481
+
482
+ blk.call(y)
483
+ end
484
+ end
485
+ end
486
+
487
+ # @type [Regexp]
488
+ JSON_CONTENT = %r{^application/(?:vnd(?:\.[^.]+)*\+)?json(?!l)}
489
+ # @type [Regexp]
490
+ JSONL_CONTENT = %r{^application/(:?x-(?:n|l)djson)|(:?(?:x-)?jsonl)}
491
+
492
+ class << self
493
+ # @api private
494
+ #
495
+ # @param y [Enumerator::Yielder]
496
+ # @param val [Object]
497
+ # @param closing [Array<Proc>]
498
+ # @param content_type [String, nil]
499
+ private def write_multipart_content(y, val:, closing:, content_type: nil)
500
+ content_line = "Content-Type: %s\r\n\r\n"
501
+
502
+ case val
503
+ in EInvoiceAPI::FilePart
504
+ return write_multipart_content(
505
+ y,
506
+ val: val.content,
507
+ closing: closing,
508
+ content_type: val.content_type
509
+ )
510
+ in Pathname
511
+ y << format(content_line, content_type || "application/octet-stream")
512
+ io = val.open(binmode: true)
513
+ closing << io.method(:close)
514
+ IO.copy_stream(io, y)
515
+ in IO
516
+ y << format(content_line, content_type || "application/octet-stream")
517
+ IO.copy_stream(val, y)
518
+ in StringIO
519
+ y << format(content_line, content_type || "application/octet-stream")
520
+ y << val.string
521
+ in -> { primitive?(_1) }
522
+ y << format(content_line, content_type || "text/plain")
523
+ y << val.to_s
524
+ else
525
+ y << format(content_line, content_type || "application/json")
526
+ y << JSON.generate(val)
527
+ end
528
+ y << "\r\n"
529
+ end
530
+
531
+ # @api private
532
+ #
533
+ # @param y [Enumerator::Yielder]
534
+ # @param boundary [String]
535
+ # @param key [Symbol, String]
536
+ # @param val [Object]
537
+ # @param closing [Array<Proc>]
538
+ private def write_multipart_chunk(y, boundary:, key:, val:, closing:)
539
+ y << "--#{boundary}\r\n"
540
+ y << "Content-Disposition: form-data"
541
+
542
+ unless key.nil?
543
+ name = ERB::Util.url_encode(key.to_s)
544
+ y << "; name=\"#{name}\""
545
+ end
546
+
547
+ case val
548
+ in EInvoiceAPI::FilePart unless val.filename.nil?
549
+ filename = ERB::Util.url_encode(val.filename)
550
+ y << "; filename=\"#{filename}\""
551
+ in Pathname | IO
552
+ filename = ERB::Util.url_encode(::File.basename(val.to_path))
553
+ y << "; filename=\"#{filename}\""
554
+ else
555
+ end
556
+ y << "\r\n"
557
+
558
+ write_multipart_content(y, val: val, closing: closing)
559
+ end
560
+
561
+ # @api private
562
+ #
563
+ # https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#special-considerations-for-multipart-content
564
+ #
565
+ # @param body [Object]
566
+ #
567
+ # @return [Array(String, Enumerable<String>)]
568
+ private def encode_multipart_streaming(body)
569
+ boundary = SecureRandom.urlsafe_base64(60)
570
+
571
+ closing = []
572
+ strio = writable_enum do |y|
573
+ case body
574
+ in Hash
575
+ body.each do |key, val|
576
+ case val
577
+ in Array if val.all? { primitive?(_1) }
578
+ val.each do |v|
579
+ write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing)
580
+ end
581
+ else
582
+ write_multipart_chunk(y, boundary: boundary, key: key, val: val, closing: closing)
583
+ end
584
+ end
585
+ else
586
+ write_multipart_chunk(y, boundary: boundary, key: nil, val: body, closing: closing)
587
+ end
588
+ y << "--#{boundary}--\r\n"
589
+ end
590
+
591
+ fused_io = fused_enum(strio) { closing.each(&:call) }
592
+ [boundary, fused_io]
593
+ end
594
+
595
+ # @api private
596
+ #
597
+ # @param headers [Hash{String=>String}]
598
+ # @param body [Object]
599
+ #
600
+ # @return [Object]
601
+ def encode_content(headers, body)
602
+ # rubocop:disable Style/CaseEquality
603
+ # rubocop:disable Layout/LineLength
604
+ content_type = headers["content-type"]
605
+ case [content_type, body]
606
+ in [EInvoiceAPI::Internal::Util::JSON_CONTENT, Hash | Array | -> { primitive?(_1) }]
607
+ [headers, JSON.generate(body)]
608
+ in [EInvoiceAPI::Internal::Util::JSONL_CONTENT, Enumerable] unless EInvoiceAPI::Internal::Type::FileInput === body
609
+ [headers, body.lazy.map { JSON.generate(_1) }]
610
+ in [%r{^multipart/form-data}, Hash | EInvoiceAPI::Internal::Type::FileInput]
611
+ boundary, strio = encode_multipart_streaming(body)
612
+ headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
613
+ [headers, strio]
614
+ in [_, Symbol | Numeric]
615
+ [headers, body.to_s]
616
+ in [_, StringIO]
617
+ [headers, body.string]
618
+ in [_, EInvoiceAPI::FilePart]
619
+ [headers, body.content]
620
+ else
621
+ [headers, body]
622
+ end
623
+ # rubocop:enable Layout/LineLength
624
+ # rubocop:enable Style/CaseEquality
625
+ end
626
+
627
+ # @api private
628
+ #
629
+ # https://www.iana.org/assignments/character-sets/character-sets.xhtml
630
+ #
631
+ # @param content_type [String]
632
+ # @param text [String]
633
+ def force_charset!(content_type, text:)
634
+ charset = /charset=([^;\s]+)/.match(content_type)&.captures&.first
635
+
636
+ return unless charset
637
+
638
+ begin
639
+ encoding = Encoding.find(charset)
640
+ text.force_encoding(encoding)
641
+ rescue ArgumentError
642
+ nil
643
+ end
644
+ end
645
+
646
+ # @api private
647
+ #
648
+ # Assumes each chunk in stream has `Encoding::BINARY`.
649
+ #
650
+ # @param headers [Hash{String=>String}, Net::HTTPHeader]
651
+ # @param stream [Enumerable<String>]
652
+ # @param suppress_error [Boolean]
653
+ #
654
+ # @raise [JSON::ParserError]
655
+ # @return [Object]
656
+ def decode_content(headers, stream:, suppress_error: false)
657
+ case (content_type = headers["content-type"])
658
+ in EInvoiceAPI::Internal::Util::JSON_CONTENT
659
+ json = stream.to_a.join
660
+ begin
661
+ JSON.parse(json, symbolize_names: true)
662
+ rescue JSON::ParserError => e
663
+ raise e unless suppress_error
664
+ json
665
+ end
666
+ in EInvoiceAPI::Internal::Util::JSONL_CONTENT
667
+ lines = decode_lines(stream)
668
+ chain_fused(lines) do |y|
669
+ lines.each { y << JSON.parse(_1, symbolize_names: true) }
670
+ end
671
+ in %r{^text/event-stream}
672
+ lines = decode_lines(stream)
673
+ decode_sse(lines)
674
+ else
675
+ text = stream.to_a.join
676
+ force_charset!(content_type, text: text)
677
+ StringIO.new(text)
678
+ end
679
+ end
680
+ end
681
+
682
+ class << self
683
+ # @api private
684
+ #
685
+ # https://doc.rust-lang.org/std/iter/trait.FusedIterator.html
686
+ #
687
+ # @param enum [Enumerable<Object>]
688
+ # @param external [Boolean]
689
+ # @param close [Proc]
690
+ #
691
+ # @return [Enumerable<Object>]
692
+ def fused_enum(enum, external: false, &close)
693
+ fused = false
694
+ iter = Enumerator.new do |y|
695
+ next if fused
696
+
697
+ fused = true
698
+ if external
699
+ loop { y << enum.next }
700
+ else
701
+ enum.each(&y)
702
+ end
703
+ ensure
704
+ close&.call
705
+ close = nil
706
+ end
707
+
708
+ iter.define_singleton_method(:rewind) do
709
+ fused = true
710
+ self
711
+ end
712
+ iter
713
+ end
714
+
715
+ # @api private
716
+ #
717
+ # @param enum [Enumerable<Object>, nil]
718
+ def close_fused!(enum)
719
+ return unless enum.is_a?(Enumerator)
720
+
721
+ # rubocop:disable Lint/UnreachableLoop
722
+ enum.rewind.each { break }
723
+ # rubocop:enable Lint/UnreachableLoop
724
+ end
725
+
726
+ # @api private
727
+ #
728
+ # @param enum [Enumerable<Object>, nil]
729
+ # @param blk [Proc]
730
+ #
731
+ # @yieldparam [Enumerator::Yielder]
732
+ # @return [Enumerable<Object>]
733
+ def chain_fused(enum, &blk)
734
+ iter = Enumerator.new { blk.call(_1) }
735
+ fused_enum(iter) { close_fused!(enum) }
736
+ end
737
+ end
738
+
739
+ class << self
740
+ # @api private
741
+ #
742
+ # Assumes Strings have been forced into having `Encoding::BINARY`.
743
+ #
744
+ # This decoder is responsible for reassembling lines split across multiple
745
+ # fragments.
746
+ #
747
+ # @param enum [Enumerable<String>]
748
+ #
749
+ # @return [Enumerable<String>]
750
+ def decode_lines(enum)
751
+ re = /(\r\n|\r|\n)/
752
+ buffer = String.new
753
+ cr_seen = nil
754
+
755
+ chain_fused(enum) do |y|
756
+ enum.each do |row|
757
+ offset = buffer.bytesize
758
+ buffer << row
759
+ while (match = re.match(buffer, cr_seen&.to_i || offset))
760
+ case [match.captures.first, cr_seen]
761
+ in ["\r", nil]
762
+ cr_seen = match.end(1)
763
+ next
764
+ in ["\r" | "\r\n", Integer]
765
+ y << buffer.slice!(..(cr_seen.pred))
766
+ else
767
+ y << buffer.slice!(..(match.end(1).pred))
768
+ end
769
+ offset = 0
770
+ cr_seen = nil
771
+ end
772
+ end
773
+
774
+ y << buffer.slice!(..(cr_seen.pred)) unless cr_seen.nil?
775
+ y << buffer unless buffer.empty?
776
+ end
777
+ end
778
+
779
+ # @api private
780
+ #
781
+ # https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream
782
+ #
783
+ # Assumes that `lines` has been decoded with `#decode_lines`.
784
+ #
785
+ # @param lines [Enumerable<String>]
786
+ #
787
+ # @return [Enumerable<Hash{Symbol=>Object}>]
788
+ def decode_sse(lines)
789
+ # rubocop:disable Metrics/BlockLength
790
+ chain_fused(lines) do |y|
791
+ blank = {event: nil, data: nil, id: nil, retry: nil}
792
+ current = {}
793
+
794
+ lines.each do |line|
795
+ case line.sub(/\R$/, "")
796
+ in ""
797
+ next if current.empty?
798
+ y << {**blank, **current}
799
+ current = {}
800
+ in /^:/
801
+ next
802
+ in /^([^:]+):\s?(.*)$/
803
+ field, value = Regexp.last_match.captures
804
+ case field
805
+ in "event"
806
+ current.merge!(event: value)
807
+ in "data"
808
+ (current[:data] ||= String.new) << (value << "\n")
809
+ in "id" unless value.include?("\0")
810
+ current.merge!(id: value)
811
+ in "retry" if /^\d+$/ =~ value
812
+ current.merge!(retry: Integer(value))
813
+ else
814
+ end
815
+ else
816
+ end
817
+ end
818
+ # rubocop:enable Metrics/BlockLength
819
+
820
+ y << {**blank, **current} unless current.empty?
821
+ end
822
+ end
823
+ end
824
+
825
+ # @api private
826
+ module SorbetRuntimeSupport
827
+ class MissingSorbetRuntimeError < ::RuntimeError
828
+ end
829
+
830
+ # @api private
831
+ #
832
+ # @return [Hash{Symbol=>Object}]
833
+ private def sorbet_runtime_constants = @sorbet_runtime_constants ||= {}
834
+
835
+ # @api private
836
+ #
837
+ # @param name [Symbol]
838
+ def const_missing(name)
839
+ super unless sorbet_runtime_constants.key?(name)
840
+
841
+ unless Object.const_defined?(:T)
842
+ message = "Trying to access a Sorbet constant #{name.inspect} without `sorbet-runtime`."
843
+ raise MissingSorbetRuntimeError.new(message)
844
+ end
845
+
846
+ sorbet_runtime_constants.fetch(name).call
847
+ end
848
+
849
+ # @api private
850
+ #
851
+ # @param name [Symbol]
852
+ #
853
+ # @return [Boolean]
854
+ def sorbet_constant_defined?(name) = sorbet_runtime_constants.key?(name)
855
+
856
+ # @api private
857
+ #
858
+ # @param name [Symbol]
859
+ # @param blk [Proc]
860
+ def define_sorbet_constant!(name, &blk) = sorbet_runtime_constants.store(name, blk)
861
+
862
+ # @api private
863
+ #
864
+ # @return [Object]
865
+ def to_sorbet_type = raise NotImplementedError
866
+
867
+ class << self
868
+ # @api private
869
+ #
870
+ # @param type [EInvoiceAPI::Internal::Util::SorbetRuntimeSupport, Object]
871
+ #
872
+ # @return [Object]
873
+ def to_sorbet_type(type)
874
+ case type
875
+ in EInvoiceAPI::Internal::Util::SorbetRuntimeSupport
876
+ type.to_sorbet_type
877
+ in Class | Module
878
+ type
879
+ in true | false
880
+ T::Boolean
881
+ else
882
+ type.class
883
+ end
884
+ end
885
+ end
886
+ end
887
+
888
+ extend EInvoiceAPI::Internal::Util::SorbetRuntimeSupport
889
+
890
+ define_sorbet_constant!(:ParsedUri) do
891
+ T.type_alias do
892
+ {
893
+ scheme: T.nilable(String),
894
+ host: T.nilable(String),
895
+ port: T.nilable(Integer),
896
+ path: T.nilable(String),
897
+ query: T::Hash[String, T::Array[String]]
898
+ }
899
+ end
900
+ end
901
+
902
+ define_sorbet_constant!(:ServerSentEvent) do
903
+ T.type_alias do
904
+ {
905
+ event: T.nilable(String),
906
+ data: T.nilable(String),
907
+ id: T.nilable(String),
908
+ retry: T.nilable(Integer)
909
+ }
910
+ end
911
+ end
912
+ end
913
+ end
914
+ end