nafru-email 0.1.1
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +316 -0
- data/lib/nafru_email/app.rb +196 -0
- data/lib/nafru_email/client.rb +83 -0
- data/lib/nafru_email/dev_outbox.rb +71 -0
- data/lib/nafru_email/error.rb +77 -0
- data/lib/nafru_email/http.rb +184 -0
- data/lib/nafru_email/pagination.rb +26 -0
- data/lib/nafru_email/resources.rb +183 -0
- data/lib/nafru_email/version.rb +8 -0
- data/lib/nafru_email/webhook.rb +58 -0
- data/lib/nafru_email.rb +12 -0
- data/sig/nafru_email.rbs +370 -0
- metadata +63 -0
data/sig/nafru_email.rbs
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# Nafru Email SDK tip imzaları. Girdi/yanıt alanları API'deki gibi snake_case; yanıtlar sembol anahtarlı Hash'tir.
|
|
2
|
+
module Nafru
|
|
3
|
+
module Email
|
|
4
|
+
VERSION: String
|
|
5
|
+
DEFAULT_BASE_URL: String
|
|
6
|
+
MAX_RESPONSE_BYTES: Integer
|
|
7
|
+
SDK_VERSION: String
|
|
8
|
+
SCOPES: Array[String]
|
|
9
|
+
|
|
10
|
+
# --- ortak
|
|
11
|
+
type list_response[T] = { object: String, data: Array[T], has_more: bool }
|
|
12
|
+
type list_query = { ?limit: Integer, ?after: String, ?before: String }
|
|
13
|
+
type deleted_response = { object: String, id: String, deleted: true }
|
|
14
|
+
type tag = { name: String, value: String }
|
|
15
|
+
type ref = { object: String, id: String }
|
|
16
|
+
type recipients = String | Array[String]
|
|
17
|
+
|
|
18
|
+
# --- e-postalar
|
|
19
|
+
type attachment = { ?content: String, ?path: String, ?filename: String, ?content_type: String, ?content_id: String }
|
|
20
|
+
type send_email_input = {
|
|
21
|
+
?from: String, to: recipients, ?cc: recipients, ?bcc: recipients, ?reply_to: recipients, ?subject: String,
|
|
22
|
+
?headers: Hash[String, String], ?tags: Array[tag], ?scheduled_at: String,
|
|
23
|
+
?html: String, ?text: String, ?attachments: Array[attachment],
|
|
24
|
+
?template: { id: String, ?variables: Hash[String | Symbol, String | Integer | Float] }
|
|
25
|
+
}
|
|
26
|
+
type batch_email_item = {
|
|
27
|
+
from: String, to: recipients, ?cc: recipients, ?bcc: recipients, ?reply_to: recipients, subject: String,
|
|
28
|
+
?headers: Hash[String, String], ?tags: Array[tag], ?scheduled_at: String, ?html: String, ?text: String
|
|
29
|
+
}
|
|
30
|
+
type email_list_item = {
|
|
31
|
+
id: String, to: Array[String], from: String, created_at: String, subject: String, bcc: Array[String]?,
|
|
32
|
+
cc: Array[String]?, reply_to: Array[String]?, last_event: String, scheduled_at: String?, message_id: String?
|
|
33
|
+
}
|
|
34
|
+
type email_event = { id: String, type: String, created_at: String, detail: Hash[Symbol, untyped] }
|
|
35
|
+
type email = {
|
|
36
|
+
object: "email", id: String, to: Array[String], from: String, created_at: String, subject: String,
|
|
37
|
+
bcc: Array[String]?, cc: Array[String]?, reply_to: Array[String]?, last_event: String, scheduled_at: String?,
|
|
38
|
+
message_id: String?, html: String?, text: String?, tags: Array[tag], events: Array[email_event]
|
|
39
|
+
}
|
|
40
|
+
type list_emails_query = { ?limit: Integer, ?after: String, ?before: String, ?status: String }
|
|
41
|
+
|
|
42
|
+
# --- alan adları
|
|
43
|
+
type domain_record = { record: String, name: String, type: String, value: String, ttl: String, status: String, ?priority: Integer }
|
|
44
|
+
type domain = {
|
|
45
|
+
id: String, name: String, status: String, created_at: String, region: String,
|
|
46
|
+
capabilities: { sending: String, receiving: String }, open_tracking: bool, click_tracking: bool, tls: String,
|
|
47
|
+
tracking_subdomain: String?
|
|
48
|
+
}
|
|
49
|
+
type domain_detail = {
|
|
50
|
+
object: "domain", id: String, name: String, status: String, created_at: String, region: String,
|
|
51
|
+
capabilities: { sending: String, receiving: String }, open_tracking: bool, click_tracking: bool, tls: String,
|
|
52
|
+
tracking_subdomain: String?, records: Array[domain_record]
|
|
53
|
+
}
|
|
54
|
+
type create_domain_input = { name: String, ?region: String, ?open_tracking: bool, ?click_tracking: bool, ?tls: String, ?tracking_subdomain: String }
|
|
55
|
+
type update_domain_input = { ?open_tracking: bool, ?click_tracking: bool, ?tls: String, ?tracking_subdomain: String? }
|
|
56
|
+
|
|
57
|
+
# --- kişiler
|
|
58
|
+
type property_value = String | Integer | Float | nil
|
|
59
|
+
type contact = { id: String, email: String, first_name: String?, last_name: String?, unsubscribed: bool, locale: String?, created_at: String }
|
|
60
|
+
type contact_detail = {
|
|
61
|
+
object: "contact", id: String, email: String, first_name: String?, last_name: String?, unsubscribed: bool,
|
|
62
|
+
locale: String?, created_at: String, properties: Hash[Symbol, { type: String, value: String | Integer | Float }]
|
|
63
|
+
}
|
|
64
|
+
type topic_subscription = "opt_in" | "opt_out"
|
|
65
|
+
type create_contact_input = {
|
|
66
|
+
email: String, ?first_name: String?, ?last_name: String?, ?unsubscribed: bool, ?locale: String?,
|
|
67
|
+
?properties: Hash[String | Symbol, property_value], ?segments: Array[{ id: String }],
|
|
68
|
+
?topics: Array[{ id: String, subscription: topic_subscription }]
|
|
69
|
+
}
|
|
70
|
+
type update_contact_input = { ?first_name: String?, ?last_name: String?, ?unsubscribed: bool, ?locale: String?, ?properties: Hash[String | Symbol, property_value] }
|
|
71
|
+
type list_contacts_query = { ?limit: Integer, ?after: String, ?before: String, ?search: String }
|
|
72
|
+
type deleted_contact = { object: "contact", contact: String, deleted: true }
|
|
73
|
+
type contact_property = { id: String, key: String, type: String, fallback_value: property_value, created_at: String }
|
|
74
|
+
type create_contact_property_input = { key: String, type: "string" | "number", ?fallback_value: property_value }
|
|
75
|
+
type update_contact_property_input = { ?fallback_value: property_value }
|
|
76
|
+
type contact_topic = { id: String, name: String, description: String?, subscription: topic_subscription, status: String }
|
|
77
|
+
type update_contact_topics_input = { topics: Array[{ id: String, subscription: topic_subscription }] }
|
|
78
|
+
|
|
79
|
+
# --- segmentler, konular
|
|
80
|
+
type segment = { id: String, name: String, created_at: String, type: String, filter: Hash[Symbol, untyped]? }
|
|
81
|
+
type create_segment_input = { name: String, ?filter: Hash[String | Symbol, untyped] }
|
|
82
|
+
type segment_ref = { object: "segment", id: String, name: String }
|
|
83
|
+
type topic = {
|
|
84
|
+
id: String, name: String, description: String?, default_subscription: topic_subscription, visibility: String,
|
|
85
|
+
double_opt_in: bool, created_at: String
|
|
86
|
+
}
|
|
87
|
+
type create_topic_input = { name: String, default_subscription: topic_subscription, ?description: String?, ?visibility: String, ?double_opt_in: bool }
|
|
88
|
+
type update_topic_input = { ?name: String, ?description: String?, ?visibility: String, ?double_opt_in: bool }
|
|
89
|
+
|
|
90
|
+
# --- kampanyalar
|
|
91
|
+
# Tekrar kuralı; saat (`HH:MM`) çalışma alanının saat diliminde. weekly.days: 0 = pazar … 6 = cumartesi.
|
|
92
|
+
# Yanıtta bilinmeyen `type` gelebilir: Hash olarak olduğu gibi döner.
|
|
93
|
+
type broadcast_recurrence = { type: "weekly", days: Array[Integer], time: String }
|
|
94
|
+
| { type: "monthly", day: Integer, time: String }
|
|
95
|
+
| { type: "interval", every_days: Integer, time: String }
|
|
96
|
+
type broadcast_data_source_input = { type: "manual" }
|
|
97
|
+
| { type: "url", url: String, ?header_name: String?, ?header_value: String? }
|
|
98
|
+
| { type: "webhook", ?regenerate_secret: bool }
|
|
99
|
+
type broadcast_data_source = { type: "manual" }
|
|
100
|
+
| { type: "url", url: String, header_name: String?, has_header_value: bool }
|
|
101
|
+
| { type: "webhook", trigger_url: String, secret: String }
|
|
102
|
+
type broadcast_list_item = {
|
|
103
|
+
id: String, name: String, segment_id: String, audience_id: String, subject: String, status: String,
|
|
104
|
+
created_at: String, scheduled_at: String?, sent_at: String?, recurrence: broadcast_recurrence?,
|
|
105
|
+
trigger_state: ("active" | "paused")?, next_run_at: String?, parent_id: String?
|
|
106
|
+
}
|
|
107
|
+
type broadcast = {
|
|
108
|
+
object: "broadcast", id: String, name: String, segment_id: String, audience_id: String, subject: String, status: String,
|
|
109
|
+
created_at: String, scheduled_at: String?, sent_at: String?, recurrence: broadcast_recurrence?,
|
|
110
|
+
trigger_state: ("active" | "paused")?, next_run_at: String?, parent_id: String?,
|
|
111
|
+
from: String, reply_to: Array[String]?, preview_text: String?, topic_id: String?, template_id: String?, html: String?,
|
|
112
|
+
text: String?, open_tracking: bool, click_tracking: bool, finished_at: String?, failure_reason: String?,
|
|
113
|
+
data: Hash[Symbol, untyped]?, data_source: broadcast_data_source?
|
|
114
|
+
}
|
|
115
|
+
type create_broadcast_input = {
|
|
116
|
+
?name: String, segment_id: String, ?topic_id: String, from: String, ?subject: String, ?reply_to: recipients,
|
|
117
|
+
?html: String, ?text: String, ?template_id: String, ?preview_text: String?, ?send: bool, ?scheduled_at: String,
|
|
118
|
+
?open_tracking: bool, ?click_tracking: bool, ?data: Hash[String | Symbol, untyped]?,
|
|
119
|
+
?data_source: broadcast_data_source_input?, ?recurrence: broadcast_recurrence?
|
|
120
|
+
}
|
|
121
|
+
# `nil` alan açıkça temizler (JSON null); verilmeyen alana dokunulmaz.
|
|
122
|
+
type update_broadcast_input = {
|
|
123
|
+
?name: String, ?segment_id: String, ?topic_id: String?, ?from: String, ?subject: String, ?reply_to: Array[String],
|
|
124
|
+
?html: String, ?text: String, ?preview_text: String?, ?open_tracking: bool, ?click_tracking: bool,
|
|
125
|
+
?data: Hash[String | Symbol, untyped]?, ?data_source: broadcast_data_source_input?, ?recurrence: broadcast_recurrence?
|
|
126
|
+
}
|
|
127
|
+
type send_broadcast_input = { ?scheduled_at: String, ?data: Hash[String | Symbol, untyped] }
|
|
128
|
+
|
|
129
|
+
# --- şablonlar ve marka
|
|
130
|
+
type template_brand_override = {
|
|
131
|
+
?accent_color: String, ?text_color: String, ?backdrop_color: String, ?canvas_color: String, ?font_family: String,
|
|
132
|
+
?link_color: String, ?content_width: Integer, ?show_header: bool, ?show_footer: bool
|
|
133
|
+
}
|
|
134
|
+
type template_brand = { mode: "inherit" | "custom" | "none", ?override: template_brand_override? }
|
|
135
|
+
type template_list_item = {
|
|
136
|
+
id: String, name: String, alias: String?, type: String, status: String, subject: String?, current_version: Integer?,
|
|
137
|
+
has_unpublished_changes: bool, published_at: String?, created_at: String, updated_at: String
|
|
138
|
+
}
|
|
139
|
+
type template_variable = { key: String, type: String, fallback_value: String? }
|
|
140
|
+
type template = Hash[Symbol, untyped] # template_list_item + object, preview_text, html, text, design, revision, variables: Array[template_variable], brand
|
|
141
|
+
type create_template_input = { name: String, ?alias: String, ?subject: String?, ?preview_text: String?, html: String, ?text: String?, ?brand: template_brand }
|
|
142
|
+
type update_template_input = {
|
|
143
|
+
?revision: Integer, ?name: String, ?alias: String?, ?subject: String?, ?preview_text: String?, ?html: String,
|
|
144
|
+
?text: String?, ?brand: template_brand
|
|
145
|
+
}
|
|
146
|
+
type template_saved = { object: "template", id: String, revision: Integer }
|
|
147
|
+
type template_published = { object: "template", id: String, version: Integer, version_id: String, revision: Integer }
|
|
148
|
+
type put_template_translation_input = { ?subject: String?, ?preview_text: String?, html: String, ?text: String? }
|
|
149
|
+
type template_translation = { locale: String, subject: String?, preview_text: String?, design_revision: Integer, updated_at: String }
|
|
150
|
+
type brand_social_link = { network: String, url: String }
|
|
151
|
+
type brand = Hash[Symbol, untyped] # object, configured, logo_*, accent_color, text_color, …, social_links: Array[brand_social_link]
|
|
152
|
+
type update_brand_input = Hash[Symbol | String, untyped] # tüm alanlar isteğe bağlı; gönderilmeyen "ayarlanmadı" olur
|
|
153
|
+
|
|
154
|
+
# --- webhook, anahtar, olay
|
|
155
|
+
type webhook = { id: String, endpoint: String, created_at: String, status: String, events: Array[String] }
|
|
156
|
+
type created_webhook = { object: "webhook", id: String, signing_secret: String }
|
|
157
|
+
type create_webhook_input = { endpoint: String, events: Array[String] }
|
|
158
|
+
type update_webhook_input = { ?endpoint: String, ?events: Array[String], ?status: "enabled" | "disabled" }
|
|
159
|
+
type api_key = { id: String, name: String, created_at: String, last_used_at: String?, permission: String, domain_id: String?, token_prefix: String }
|
|
160
|
+
type create_api_key_input = { name: String, ?permission: "full_access" | "sending_access", ?domain_id: String }
|
|
161
|
+
type event_properties = Hash[String | Symbol, String | Integer | Float | bool | nil]
|
|
162
|
+
type send_event_input = { name: String, contact: { email: String } | { id: String }, ?properties: event_properties, ?occurred_at: String, ?unsubscribed: bool }
|
|
163
|
+
type event_item = {
|
|
164
|
+
id: String, name: String, contact_id: String, email: String, properties: Hash[Symbol, untyped], source: String,
|
|
165
|
+
occurred_at: String, created_at: String
|
|
166
|
+
}
|
|
167
|
+
type list_events_query = { ?limit: Integer, ?after: String, ?before: String, ?name: String, ?contact_id: String, ?email: String }
|
|
168
|
+
|
|
169
|
+
# --- uygulama ("Nafru ile bağlan")
|
|
170
|
+
type connection_status = {
|
|
171
|
+
object: "connection", id: String, ready: bool, missing: Array[String], hints: Array[String], scopes: Array[String],
|
|
172
|
+
billing_mode: "customer_pays" | "app_pays", setup_url: String, workspace: { name: String }
|
|
173
|
+
}
|
|
174
|
+
type connection_senders = { domains: Array[{ id: String, name: String }], default_from: String? }
|
|
175
|
+
type connection_template = { key: String, name: String, source: "workspace" | "pack", customized_from_pack: bool }
|
|
176
|
+
|
|
177
|
+
# `exchange` sonucu; `inspect`/`to_s` yenileme belirtecini göstermez.
|
|
178
|
+
class ConnectionGrant < Struct[untyped]
|
|
179
|
+
attr_accessor connection_id: String
|
|
180
|
+
attr_accessor refresh_token: String
|
|
181
|
+
attr_accessor scopes: Array[String]
|
|
182
|
+
def initialize: (connection_id: String, refresh_token: String, scopes: Array[String]) -> void
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
class Error < StandardError
|
|
186
|
+
attr_reader status_code: Integer?
|
|
187
|
+
attr_reader name: String
|
|
188
|
+
attr_reader errors: Array[{ field: String, message: String, ?i18nTranslationKey: String }]?
|
|
189
|
+
attr_reader retry_after: Numeric?
|
|
190
|
+
def initialize: (String message, name: String, ?status_code: Integer?, ?errors: Array[Hash[Symbol, String]]?, ?retry_after: Numeric?) -> void
|
|
191
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class Response < Struct[untyped]
|
|
195
|
+
attr_accessor status: Integer
|
|
196
|
+
attr_accessor headers: Hash[String, String]
|
|
197
|
+
attr_accessor body: String?
|
|
198
|
+
attr_accessor reason: String?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
interface _Transport
|
|
202
|
+
def call: (method: String, url: String, headers: Hash[String, String], body: String?, timeout: Numeric) -> Response
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def self.paginate: [T] (^(Hash[Symbol, untyped]) -> list_response[T], ?Hash[Symbol, untyped]) -> Enumerator[T, void]
|
|
206
|
+
def self.create_pkce: () -> { verifier: String, challenge: String }
|
|
207
|
+
|
|
208
|
+
module Webhook
|
|
209
|
+
MAX_SIGNATURES: Integer
|
|
210
|
+
def self.verify: (payload: String, headers: { ?id: String?, ?timestamp: String?, ?signature: String? }?, secret: String,
|
|
211
|
+
?tolerance_seconds: Integer, ?now: Time | Numeric) -> bool
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class Connect
|
|
215
|
+
def authorize_url: (redirect_uri: String, state: String, scopes: Array[String], ?login_hint: String?) -> { url: String, code_verifier: String }
|
|
216
|
+
def exchange: (code: String, code_verifier: String, redirect_uri: String) -> ConnectionGrant
|
|
217
|
+
def revoke: (refresh_token: String) -> nil
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
class Connection
|
|
221
|
+
attr_reader id: String
|
|
222
|
+
def status: () -> connection_status
|
|
223
|
+
def senders: () -> untyped # .list -> connection_senders
|
|
224
|
+
def templates: () -> untyped # .list -> list_response[connection_template]
|
|
225
|
+
def emails: () -> untyped # .send / .get / .list (Resources::Emails ile aynı imza)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
module Resources
|
|
229
|
+
class Emails
|
|
230
|
+
def send: (send_email_input input, ?idempotency_key: String?) -> { id: String }
|
|
231
|
+
def batch: (Array[batch_email_item] input, ?idempotency_key: String?) -> { data: Array[{ id: String }] }
|
|
232
|
+
def get: (String id) -> email
|
|
233
|
+
def list: (?list_emails_query query) -> list_response[email_list_item]
|
|
234
|
+
def update: (String id, { scheduled_at: String } input) -> ref
|
|
235
|
+
def cancel: (String id) -> ref
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
class Domains
|
|
239
|
+
def create: (create_domain_input input) -> domain_detail
|
|
240
|
+
def get: (String id) -> domain_detail
|
|
241
|
+
def list: (?list_query query) -> list_response[domain]
|
|
242
|
+
def update: (String id, update_domain_input input) -> ref
|
|
243
|
+
def remove: (String id) -> deleted_response
|
|
244
|
+
def verify: (String id) -> ref
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class Contacts
|
|
248
|
+
attr_reader segments: ContactSegments
|
|
249
|
+
attr_reader topics: ContactTopics
|
|
250
|
+
def create: (create_contact_input input) -> ref
|
|
251
|
+
def get: (String id_or_email) -> contact_detail
|
|
252
|
+
def list: (?list_contacts_query query) -> list_response[contact]
|
|
253
|
+
def update: (String id_or_email, update_contact_input input) -> ref
|
|
254
|
+
def remove: (String id_or_email) -> deleted_contact
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class ContactSegments
|
|
258
|
+
def list: (String id_or_email, ?list_query query) -> list_response[segment]
|
|
259
|
+
def add: (String id_or_email, String segment_id) -> { id: String }
|
|
260
|
+
def remove: (String id_or_email, String segment_id) -> { id: String, deleted: true }
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
class ContactTopics
|
|
264
|
+
def list: (String id_or_email, ?list_query query) -> list_response[contact_topic]
|
|
265
|
+
def update: (String id_or_email, update_contact_topics_input input) -> ref
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class ContactProperties
|
|
269
|
+
def create: (create_contact_property_input input) -> ref
|
|
270
|
+
def get: (String id) -> Hash[Symbol, untyped]
|
|
271
|
+
def list: (?list_query query) -> list_response[contact_property]
|
|
272
|
+
def update: (String id, update_contact_property_input input) -> ref
|
|
273
|
+
def remove: (String id) -> deleted_response
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
class Segments
|
|
277
|
+
def create: (create_segment_input input) -> segment_ref
|
|
278
|
+
def get: (String id) -> Hash[Symbol, untyped]
|
|
279
|
+
def list: (?list_query query) -> list_response[segment]
|
|
280
|
+
def remove: (String id) -> deleted_response
|
|
281
|
+
def contacts: (String id, ?{ ?limit: Integer, ?after: String } query) -> list_response[contact]
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
class Topics
|
|
285
|
+
def create: (create_topic_input input) -> ref
|
|
286
|
+
def get: (String id) -> Hash[Symbol, untyped]
|
|
287
|
+
def list: (?list_query query) -> list_response[topic]
|
|
288
|
+
def update: (String id, update_topic_input input) -> ref
|
|
289
|
+
def remove: (String id) -> deleted_response
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
class Broadcasts
|
|
293
|
+
def create: (create_broadcast_input input) -> ref
|
|
294
|
+
def get: (String id) -> broadcast
|
|
295
|
+
def list: (?list_query query) -> list_response[broadcast_list_item]
|
|
296
|
+
def update: (String id, update_broadcast_input input) -> ref
|
|
297
|
+
def remove: (String id) -> deleted_response
|
|
298
|
+
def send: (String id, ?send_broadcast_input input) -> ref
|
|
299
|
+
def cancel: (String id) -> ref
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
class Templates
|
|
303
|
+
def create: (create_template_input input) -> template_saved
|
|
304
|
+
def get: (String id_or_alias) -> template
|
|
305
|
+
def list: (?list_query query) -> list_response[template_list_item]
|
|
306
|
+
def update: (String id_or_alias, update_template_input input) -> template_saved
|
|
307
|
+
def remove: (String id_or_alias) -> deleted_response
|
|
308
|
+
def publish: (String id_or_alias) -> template_published
|
|
309
|
+
def duplicate: (String id_or_alias) -> ref
|
|
310
|
+
def put_translation: (String id_or_alias, String locale, put_template_translation_input input) -> template_translation
|
|
311
|
+
def remove_translation: (String id_or_alias, String locale) -> { object: String, locale: String, deleted: true }
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
class Brand
|
|
315
|
+
def get: () -> brand
|
|
316
|
+
def update: (update_brand_input input) -> brand
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
class Webhooks
|
|
320
|
+
def create: (create_webhook_input input) -> created_webhook
|
|
321
|
+
def get: (String id) -> Hash[Symbol, untyped]
|
|
322
|
+
def list: (?list_query query) -> list_response[webhook]
|
|
323
|
+
def update: (String id, update_webhook_input input) -> ref
|
|
324
|
+
def remove: (String id) -> deleted_response
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
class ApiKeys
|
|
328
|
+
def create: (create_api_key_input input) -> { id: String, token: String }
|
|
329
|
+
def list: (?list_query query) -> list_response[api_key]
|
|
330
|
+
def remove: (String id) -> deleted_response
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
class Events
|
|
334
|
+
def send: (send_event_input input, ?idempotency_key: String?) -> { id: String }
|
|
335
|
+
def batch: (Array[send_event_input] input, ?idempotency_key: String?) -> { data: Array[{ id: String }] }
|
|
336
|
+
def list: (?list_events_query query) -> list_response[event_item]
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# API anahtarıyla istemci (Resend tarzı). `api_key` boşsa `NAFRU_API_KEY` okunur.
|
|
343
|
+
class NafruEmail
|
|
344
|
+
def initialize: (?String? api_key, ?base_url: String?, ?transport: Nafru::Email::_Transport?, ?max_retries: Integer,
|
|
345
|
+
?timeout: Numeric, ?dev_outbox: String | false | nil) -> void
|
|
346
|
+
attr_reader emails: Nafru::Email::Resources::Emails
|
|
347
|
+
attr_reader domains: Nafru::Email::Resources::Domains
|
|
348
|
+
attr_reader contacts: Nafru::Email::Resources::Contacts
|
|
349
|
+
attr_reader contact_properties: Nafru::Email::Resources::ContactProperties
|
|
350
|
+
attr_reader segments: Nafru::Email::Resources::Segments
|
|
351
|
+
attr_reader topics: Nafru::Email::Resources::Topics
|
|
352
|
+
attr_reader broadcasts: Nafru::Email::Resources::Broadcasts
|
|
353
|
+
attr_reader templates: Nafru::Email::Resources::Templates
|
|
354
|
+
attr_reader brand: Nafru::Email::Resources::Brand
|
|
355
|
+
attr_reader webhooks: Nafru::Email::Resources::Webhooks
|
|
356
|
+
attr_reader api_keys: Nafru::Email::Resources::ApiKeys
|
|
357
|
+
attr_reader events: Nafru::Email::Resources::Events
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# "Nafru ile bağlan" (OAuth + PKCE) fabrikası.
|
|
361
|
+
class NafruConnect
|
|
362
|
+
def initialize: (client_id: String, client_secret: String, ?base_url: String?, ?web_url: String?,
|
|
363
|
+
?transport: Nafru::Email::_Transport?, ?max_retries: Integer, ?timeout: Numeric,
|
|
364
|
+
?dev_outbox: String | false | nil) -> void
|
|
365
|
+
def authorize_url: (redirect_uri: String, state: String, scopes: Array[String], ?login_hint: String?) -> { url: String, code_verifier: String }
|
|
366
|
+
def exchange: (code: String, code_verifier: String, redirect_uri: String) -> Nafru::Email::ConnectionGrant
|
|
367
|
+
def revoke: (refresh_token: String) -> nil
|
|
368
|
+
def connection: (String connection_id, refresh_token: String, ?on_token_refresh: ^({ refresh_token: String }) -> void)
|
|
369
|
+
?{ ({ refresh_token: String }) -> void } -> Nafru::Email::Connection
|
|
370
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: nafru-email
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nafru
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-11-10 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: 'Nafru Email Ruby SDK: send transactional and marketing email from Ruby
|
|
14
|
+
with a Resend-compatible email API. Contacts, broadcasts, templates, custom events,
|
|
15
|
+
webhook verification and Connect with Nafru (OAuth). No dependencies (net/http,
|
|
16
|
+
json, openssl).'
|
|
17
|
+
email:
|
|
18
|
+
executables: []
|
|
19
|
+
extensions: []
|
|
20
|
+
extra_rdoc_files: []
|
|
21
|
+
files:
|
|
22
|
+
- LICENSE
|
|
23
|
+
- README.md
|
|
24
|
+
- lib/nafru_email.rb
|
|
25
|
+
- lib/nafru_email/app.rb
|
|
26
|
+
- lib/nafru_email/client.rb
|
|
27
|
+
- lib/nafru_email/dev_outbox.rb
|
|
28
|
+
- lib/nafru_email/error.rb
|
|
29
|
+
- lib/nafru_email/http.rb
|
|
30
|
+
- lib/nafru_email/pagination.rb
|
|
31
|
+
- lib/nafru_email/resources.rb
|
|
32
|
+
- lib/nafru_email/version.rb
|
|
33
|
+
- lib/nafru_email/webhook.rb
|
|
34
|
+
- sig/nafru_email.rbs
|
|
35
|
+
homepage: https://github.com/nafrucom/nafru-email
|
|
36
|
+
licenses:
|
|
37
|
+
- MIT
|
|
38
|
+
metadata:
|
|
39
|
+
homepage_uri: https://github.com/nafrucom/nafru-email
|
|
40
|
+
source_code_uri: https://github.com/nafrucom/nafru-email-sdks/tree/main/ruby
|
|
41
|
+
bug_tracker_uri: https://github.com/nafrucom/nafru-email-sdks/issues
|
|
42
|
+
rubygems_mfa_required: 'true'
|
|
43
|
+
post_install_message:
|
|
44
|
+
rdoc_options: []
|
|
45
|
+
require_paths:
|
|
46
|
+
- lib
|
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
|
+
requirements:
|
|
49
|
+
- - ">="
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '3.1'
|
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '0'
|
|
57
|
+
requirements: []
|
|
58
|
+
rubygems_version: 3.5.22
|
|
59
|
+
signing_key:
|
|
60
|
+
specification_version: 4
|
|
61
|
+
summary: 'Official Ruby SDK for the Nafru Email API: send transactional email from
|
|
62
|
+
Ruby'
|
|
63
|
+
test_files: []
|