flodesk 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +101 -0
- data/LICENSE.txt +21 -0
- data/README.md +351 -0
- data/Rakefile +12 -0
- data/lib/flodesk/auth.rb +32 -0
- data/lib/flodesk/client.rb +84 -0
- data/lib/flodesk/coercion.rb +69 -0
- data/lib/flodesk/connection.rb +179 -0
- data/lib/flodesk/enums.rb +42 -0
- data/lib/flodesk/errors.rb +139 -0
- data/lib/flodesk/instrumentation.rb +35 -0
- data/lib/flodesk/objects/batch_item_error.rb +29 -0
- data/lib/flodesk/objects/batch_result.rb +44 -0
- data/lib/flodesk/objects/campaign.rb +28 -0
- data/lib/flodesk/objects/custom_field.rb +21 -0
- data/lib/flodesk/objects/page.rb +72 -0
- data/lib/flodesk/objects/segment.rb +36 -0
- data/lib/flodesk/objects/subscriber.rb +39 -0
- data/lib/flodesk/objects/webhook.rb +24 -0
- data/lib/flodesk/objects/workflow.rb +22 -0
- data/lib/flodesk/rails/railtie.rb +19 -0
- data/lib/flodesk/rails.rb +8 -0
- data/lib/flodesk/rate_limit.rb +35 -0
- data/lib/flodesk/redaction.rb +46 -0
- data/lib/flodesk/resources/base.rb +122 -0
- data/lib/flodesk/resources/campaigns.rb +121 -0
- data/lib/flodesk/resources/custom_fields.rb +47 -0
- data/lib/flodesk/resources/segments.rb +49 -0
- data/lib/flodesk/resources/subscribers.rb +239 -0
- data/lib/flodesk/resources/webhooks.rb +93 -0
- data/lib/flodesk/resources/workflows.rb +75 -0
- data/lib/flodesk/response.rb +35 -0
- data/lib/flodesk/retry_policy.rb +46 -0
- data/lib/flodesk/test_helpers.rb +152 -0
- data/lib/flodesk/version.rb +5 -0
- data/lib/flodesk/webhooks/event.rb +78 -0
- data/lib/flodesk/webhooks/handler.rb +167 -0
- data/lib/flodesk/webhooks/verification.rb +61 -0
- data/lib/flodesk.rb +59 -0
- data/lib/generators/flodesk/install_generator.rb +61 -0
- data/lib/generators/flodesk/templates/initializer.rb.tt +28 -0
- data/sig/flodesk/client.rbs +91 -0
- data/sig/flodesk/errors.rbs +51 -0
- data/sig/flodesk/objects.rbs +137 -0
- data/sig/flodesk/resources.rbs +129 -0
- data/sig/flodesk/webhooks.rbs +57 -0
- data/sig/flodesk.rbs +61 -0
- metadata +97 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Immutable response value objects.
|
|
2
|
+
#
|
|
3
|
+
# Every object exposes `raw` / `#to_h` returning the payload exactly as the API
|
|
4
|
+
# sent it, so a field Flodesk adds is reachable without a gem release.
|
|
5
|
+
module Flodesk
|
|
6
|
+
class Subscriber
|
|
7
|
+
attr_reader id: String?
|
|
8
|
+
attr_reader status: enum_value
|
|
9
|
+
attr_reader email: String?
|
|
10
|
+
attr_reader source: enum_value
|
|
11
|
+
attr_reader first_name: String?
|
|
12
|
+
attr_reader last_name: String?
|
|
13
|
+
attr_reader segments: Array[Segment]
|
|
14
|
+
attr_reader custom_fields: Hash[String, String?]
|
|
15
|
+
attr_reader optin_ip: String?
|
|
16
|
+
attr_reader optin_timestamp: timestamp
|
|
17
|
+
attr_reader created_at: timestamp
|
|
18
|
+
attr_reader raw: payload
|
|
19
|
+
|
|
20
|
+
def self.from: (payload?) -> Subscriber?
|
|
21
|
+
def self.members: () -> Array[Symbol]
|
|
22
|
+
def to_h: () -> payload
|
|
23
|
+
def active?: () -> bool
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Segment
|
|
27
|
+
attr_reader id: String?
|
|
28
|
+
attr_reader name: String?
|
|
29
|
+
attr_reader color: String?
|
|
30
|
+
attr_reader total_active_subscribers: Integer?
|
|
31
|
+
attr_reader created_at: timestamp
|
|
32
|
+
# "static" or "dynamic"; not symbolized, as the spec declares no enum.
|
|
33
|
+
attr_reader segment_type: String?
|
|
34
|
+
attr_reader raw: payload
|
|
35
|
+
|
|
36
|
+
def self.from: (payload?) -> Segment?
|
|
37
|
+
def self.members: () -> Array[Symbol]
|
|
38
|
+
def to_h: () -> payload
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class CustomField
|
|
42
|
+
attr_reader key: String?
|
|
43
|
+
attr_reader label: String?
|
|
44
|
+
attr_reader raw: payload
|
|
45
|
+
|
|
46
|
+
def self.from: (payload?) -> CustomField?
|
|
47
|
+
def self.members: () -> Array[Symbol]
|
|
48
|
+
def to_h: () -> payload
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class Workflow
|
|
52
|
+
attr_reader id: String?
|
|
53
|
+
attr_reader name: String?
|
|
54
|
+
attr_reader raw: payload
|
|
55
|
+
|
|
56
|
+
def self.from: (payload?) -> Workflow?
|
|
57
|
+
def self.members: () -> Array[Symbol]
|
|
58
|
+
def to_h: () -> payload
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class Webhook
|
|
62
|
+
attr_reader id: String?
|
|
63
|
+
attr_reader post_url: String?
|
|
64
|
+
attr_reader events: Array[String]
|
|
65
|
+
attr_reader created_at: timestamp
|
|
66
|
+
attr_reader raw: payload
|
|
67
|
+
|
|
68
|
+
def self.from: (payload?) -> Webhook?
|
|
69
|
+
def self.members: () -> Array[Symbol]
|
|
70
|
+
def to_h: () -> payload
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Campaign
|
|
74
|
+
attr_reader id: String?
|
|
75
|
+
attr_reader name: String?
|
|
76
|
+
attr_reader subject: String?
|
|
77
|
+
attr_reader status: enum_value
|
|
78
|
+
attr_reader created_at: timestamp
|
|
79
|
+
attr_reader updated_at: timestamp
|
|
80
|
+
attr_reader raw: payload
|
|
81
|
+
|
|
82
|
+
def self.from: (payload?) -> Campaign?
|
|
83
|
+
def self.members: () -> Array[Symbol]
|
|
84
|
+
def to_h: () -> payload
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# A single record's failure within a batch operation.
|
|
88
|
+
class BatchItemError
|
|
89
|
+
attr_reader index: Integer?
|
|
90
|
+
attr_reader email: String?
|
|
91
|
+
attr_reader id: String?
|
|
92
|
+
attr_reader code: String?
|
|
93
|
+
attr_reader message: String?
|
|
94
|
+
attr_reader raw: payload
|
|
95
|
+
|
|
96
|
+
def self.from: (payload?) -> BatchItemError?
|
|
97
|
+
def self.members: () -> Array[Symbol]
|
|
98
|
+
def to_h: () -> payload
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The outcome of a batch operation, which may be a partial success.
|
|
102
|
+
class BatchResult
|
|
103
|
+
attr_reader successes: Array[Subscriber]
|
|
104
|
+
attr_reader failures: Array[BatchItemError]
|
|
105
|
+
attr_reader raw: payload
|
|
106
|
+
|
|
107
|
+
def self.from: (payload?) -> BatchResult
|
|
108
|
+
def self.members: () -> Array[Symbol]
|
|
109
|
+
def success?: () -> bool
|
|
110
|
+
def size: () -> Integer
|
|
111
|
+
def failed_emails: () -> Array[String]
|
|
112
|
+
def to_h: () -> payload
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# One page of a list response.
|
|
116
|
+
class Page
|
|
117
|
+
include Enumerable[untyped]
|
|
118
|
+
|
|
119
|
+
attr_reader items: Array[untyped]
|
|
120
|
+
attr_reader page: Integer?
|
|
121
|
+
attr_reader per_page: Integer?
|
|
122
|
+
attr_reader total_pages: Integer?
|
|
123
|
+
attr_reader total_items: Integer?
|
|
124
|
+
attr_reader raw: payload
|
|
125
|
+
attr_reader fetcher: ^(Integer) -> Page?
|
|
126
|
+
|
|
127
|
+
def self.from: (payload?, klass: untyped, ?fetcher: (^(Integer) -> Page?)?) -> Page
|
|
128
|
+
def self.members: () -> Array[Symbol]
|
|
129
|
+
def each: () { (untyped) -> void } -> void
|
|
130
|
+
| () -> Enumerator[untyped, void]
|
|
131
|
+
def empty?: () -> bool
|
|
132
|
+
def more_pages?: () -> bool
|
|
133
|
+
def to_h: () -> payload
|
|
134
|
+
def auto_paging_each: () { (untyped) -> void } -> void
|
|
135
|
+
| () -> Enumerator[untyped, void]
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module Flodesk
|
|
2
|
+
module Resources
|
|
3
|
+
# Shared behavior for resource namespaces.
|
|
4
|
+
class Base
|
|
5
|
+
MAX_PER_PAGE: Integer
|
|
6
|
+
UNRESERVED: Regexp
|
|
7
|
+
|
|
8
|
+
def initialize: (Client) -> void
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Subscribers < Base
|
|
12
|
+
PATH: String
|
|
13
|
+
MAX_SEGMENTS: Integer
|
|
14
|
+
MAX_BATCH_SIZE: Integer
|
|
15
|
+
|
|
16
|
+
def list: (
|
|
17
|
+
?page: Integer?, ?per_page: Integer?,
|
|
18
|
+
?status: (Symbol | String)?, ?segment_id: String?
|
|
19
|
+
) -> Page
|
|
20
|
+
|
|
21
|
+
def auto_paging_each: (
|
|
22
|
+
?page: Integer?, ?per_page: Integer?,
|
|
23
|
+
?status: (Symbol | String)?, ?segment_id: String?
|
|
24
|
+
) { (Subscriber) -> void } -> void
|
|
25
|
+
| (
|
|
26
|
+
?page: Integer?, ?per_page: Integer?,
|
|
27
|
+
?status: (Symbol | String)?, ?segment_id: String?
|
|
28
|
+
) -> Enumerator[Subscriber, void]
|
|
29
|
+
|
|
30
|
+
def retrieve: (String) -> Subscriber?
|
|
31
|
+
def upsert: (**untyped) -> Subscriber?
|
|
32
|
+
def batch_upsert: (
|
|
33
|
+
Array[Hash[untyped, untyped]], ?raise_on_failure: bool
|
|
34
|
+
) -> BatchResult
|
|
35
|
+
def add_to_segments: (String, Array[String]) -> Subscriber?
|
|
36
|
+
def remove_from_segments: (String, Array[String]) -> Subscriber?
|
|
37
|
+
def unsubscribe: (String) -> Subscriber?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Segments < Base
|
|
41
|
+
PATH: String
|
|
42
|
+
|
|
43
|
+
def list: (?page: Integer?, ?per_page: Integer?) -> Page
|
|
44
|
+
def auto_paging_each: (?page: Integer?, ?per_page: Integer?) { (Segment) -> void } -> void
|
|
45
|
+
| (?page: Integer?, ?per_page: Integer?) -> Enumerator[Segment, void]
|
|
46
|
+
def retrieve: (String) -> Segment?
|
|
47
|
+
def create: (name: String, ?color: String?) -> Segment?
|
|
48
|
+
def colors: () -> untyped
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class CustomFields < Base
|
|
52
|
+
PATH: String
|
|
53
|
+
|
|
54
|
+
def list: (?page: Integer?, ?per_page: Integer?) -> Page
|
|
55
|
+
def auto_paging_each: (?page: Integer?, ?per_page: Integer?) { (CustomField) -> void } -> void
|
|
56
|
+
| (?page: Integer?, ?per_page: Integer?) -> Enumerator[CustomField, void]
|
|
57
|
+
def list_all: () -> Array[CustomField]
|
|
58
|
+
def create: (label: String) -> CustomField?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class Workflows < Base
|
|
62
|
+
PATH: String
|
|
63
|
+
# This endpoint alone spells its page-size parameter `perPage`.
|
|
64
|
+
PER_PAGE_KEY: String
|
|
65
|
+
|
|
66
|
+
def list: (
|
|
67
|
+
?page: Integer?, ?per_page: Integer?,
|
|
68
|
+
?statuses: (String | Symbol | Array[String | Symbol])?
|
|
69
|
+
) -> Page
|
|
70
|
+
|
|
71
|
+
def auto_paging_each: (
|
|
72
|
+
?page: Integer?, ?per_page: Integer?,
|
|
73
|
+
?statuses: (String | Symbol | Array[String | Symbol])?
|
|
74
|
+
) { (Workflow) -> void } -> void
|
|
75
|
+
| (
|
|
76
|
+
?page: Integer?, ?per_page: Integer?,
|
|
77
|
+
?statuses: (String | Symbol | Array[String | Symbol])?
|
|
78
|
+
) -> Enumerator[Workflow, void]
|
|
79
|
+
|
|
80
|
+
# Returns nil: the endpoint responds 204.
|
|
81
|
+
def add_subscriber: (String, ?id: String?, ?email: String?) -> nil
|
|
82
|
+
# Returns nil: the endpoint responds 204.
|
|
83
|
+
def remove_subscriber: (String, String) -> nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class Webhooks < Base
|
|
87
|
+
PATH: String
|
|
88
|
+
|
|
89
|
+
def list: (?page: Integer?, ?per_page: Integer?) -> Page
|
|
90
|
+
def auto_paging_each: (?page: Integer?, ?per_page: Integer?) { (Webhook) -> void } -> void
|
|
91
|
+
| (?page: Integer?, ?per_page: Integer?) -> Enumerator[Webhook, void]
|
|
92
|
+
def retrieve: (String) -> Webhook?
|
|
93
|
+
def create: (
|
|
94
|
+
name: String, post_url: String, events: (String | Array[String])
|
|
95
|
+
) -> Webhook?
|
|
96
|
+
def update: (
|
|
97
|
+
String, ?name: String?, ?post_url: String?,
|
|
98
|
+
?events: (String | Array[String])?
|
|
99
|
+
) -> Webhook?
|
|
100
|
+
# Returns nil: the endpoint responds 204.
|
|
101
|
+
def delete: (String) -> nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class Campaigns < Base
|
|
105
|
+
PATH: String
|
|
106
|
+
# This endpoint's filters are PascalCase, unlike anything else in the API.
|
|
107
|
+
FILTER_KEYS: Hash[Symbol, String]
|
|
108
|
+
|
|
109
|
+
def list: (?page: Integer?, ?per_page: Integer?, **untyped) -> Page
|
|
110
|
+
def auto_paging_each: (
|
|
111
|
+
?page: Integer?, ?per_page: Integer?, **untyped
|
|
112
|
+
) { (Campaign) -> void } -> void
|
|
113
|
+
| (?page: Integer?, ?per_page: Integer?, **untyped) -> Enumerator[Campaign, void]
|
|
114
|
+
|
|
115
|
+
# NEVER retried: a retry could send the campaign to the whole list twice.
|
|
116
|
+
def publish_canva: (
|
|
117
|
+
?bundle_url: String?, ?title: String?, ?design_token: String?,
|
|
118
|
+
?page_id: String?, ?campaign_id: String?
|
|
119
|
+
) -> untyped
|
|
120
|
+
|
|
121
|
+
# NEVER retried, for the same reason as publish_canva.
|
|
122
|
+
def publish_studio: (
|
|
123
|
+
?html: String?, ?title: String?, ?campaign_id: String?, ?asset_id: String?
|
|
124
|
+
) -> untyped
|
|
125
|
+
|
|
126
|
+
def canva_design_state: () -> untyped
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Flodesk
|
|
2
|
+
# Handling of inbound webhook deliveries.
|
|
3
|
+
#
|
|
4
|
+
# Flodesk signs nothing, so a verification strategy is mandatory.
|
|
5
|
+
module Webhooks
|
|
6
|
+
STRATEGIES: Array[Symbol]
|
|
7
|
+
|
|
8
|
+
class VerificationError < Error
|
|
9
|
+
def initialize: (?String) -> void
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class InvalidPayloadError < Error
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module Verification
|
|
16
|
+
MIN_TOKEN_LENGTH: Integer
|
|
17
|
+
TOKEN_BYTES: Integer
|
|
18
|
+
|
|
19
|
+
def self.generate_token: () -> String
|
|
20
|
+
def self.secure_compare: (String?, String?) -> bool
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# A verified inbound webhook event.
|
|
24
|
+
class Event
|
|
25
|
+
attr_reader event_name: String?
|
|
26
|
+
attr_reader event_time: timestamp
|
|
27
|
+
attr_reader subscriber: Subscriber?
|
|
28
|
+
attr_reader segment: Segment?
|
|
29
|
+
attr_reader webhook_id: String?
|
|
30
|
+
attr_reader raw: payload
|
|
31
|
+
|
|
32
|
+
def self.from: (payload, ?subscriber: Subscriber?) -> Event
|
|
33
|
+
def self.members: () -> Array[Symbol]
|
|
34
|
+
def to_h: () -> payload
|
|
35
|
+
def known?: () -> bool
|
|
36
|
+
# SHA-256 of the composed identity, since events carry no unique id.
|
|
37
|
+
def dedupe_key: () -> String
|
|
38
|
+
def inspect: () -> String
|
|
39
|
+
def to_s: () -> String
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Handler
|
|
43
|
+
def self.generate_token: () -> String
|
|
44
|
+
|
|
45
|
+
def initialize: (
|
|
46
|
+
?token: String?, ?verify: Symbol?, ?client: Client?
|
|
47
|
+
) -> void
|
|
48
|
+
|
|
49
|
+
def call: (body: String?, ?token: String?) -> Event
|
|
50
|
+
|
|
51
|
+
# Returns a Rack triple: [status, headers, body].
|
|
52
|
+
def respond: (
|
|
53
|
+
body: String?, ?token: String?, ?on_error: (^(Exception) -> void)?
|
|
54
|
+
) ?{ (Event) -> void } -> [Integer, Hash[String, String], Array[String]]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/sig/flodesk.rbs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Core module, configuration constants, and shared type aliases.
|
|
2
|
+
module Flodesk
|
|
3
|
+
VERSION: String
|
|
4
|
+
DEFAULT_BASE_URL: String
|
|
5
|
+
MAX_BACKOFF_SECONDS: Integer
|
|
6
|
+
|
|
7
|
+
# A parsed JSON object as received from the API.
|
|
8
|
+
type payload = Hash[String, untyped]
|
|
9
|
+
|
|
10
|
+
# An enum value: a Symbol when documented, otherwise the raw String.
|
|
11
|
+
type enum_value = Symbol | String | nil
|
|
12
|
+
|
|
13
|
+
# An ISO 8601 timestamp: a Time when parseable, otherwise the raw String.
|
|
14
|
+
type timestamp = Time | String | nil
|
|
15
|
+
|
|
16
|
+
# Closed enumerations documented by the API description.
|
|
17
|
+
module Enums
|
|
18
|
+
SUBSCRIBER_STATUSES: Array[String]
|
|
19
|
+
SUBSCRIBER_SOURCES: Array[String]
|
|
20
|
+
WORKFLOW_STATUSES: Array[String]
|
|
21
|
+
CAMPAIGN_STATUSES: Array[String]
|
|
22
|
+
WEBHOOK_EVENTS: Array[String]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Coercion
|
|
26
|
+
def self.enum: (untyped, Array[String]) -> enum_value
|
|
27
|
+
def self.time: (untyped) -> timestamp
|
|
28
|
+
def self.array_of: (untyped, untyped) -> Array[untyped]
|
|
29
|
+
def self.string_hash: (untyped) -> Hash[String, String?]
|
|
30
|
+
def self.snapshot: (untyped) -> untyped
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module Redaction
|
|
34
|
+
SENSITIVE_KEYS: Array[String]
|
|
35
|
+
PLACEHOLDER: String
|
|
36
|
+
EMAIL_IN_SEGMENT: Regexp
|
|
37
|
+
|
|
38
|
+
def self.path: (untyped) -> String
|
|
39
|
+
def self.payload: (untyped) -> untyped
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module Instrumentation
|
|
43
|
+
EVENT_NAME: String
|
|
44
|
+
|
|
45
|
+
def self.available?: () -> bool
|
|
46
|
+
def self.request: (
|
|
47
|
+
method: Symbol, path: String, status: Integer,
|
|
48
|
+
duration: Float, attempt: Integer, rate_limit_remaining: Integer?
|
|
49
|
+
) -> void
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module RateLimit
|
|
53
|
+
class State
|
|
54
|
+
attr_reader limit: Integer?
|
|
55
|
+
attr_reader remaining: Integer?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.record: (Client, Response) -> void
|
|
59
|
+
def self.last: (Client) -> State?
|
|
60
|
+
end
|
|
61
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: flodesk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jim
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: |
|
|
13
|
+
A dependency-free Ruby client for the Flodesk API, built for Rails apps.
|
|
14
|
+
Covers subscribers, segments, custom fields, workflows, webhooks and
|
|
15
|
+
campaigns, and hides the API's rough edges: non-uniform pagination
|
|
16
|
+
parameters, batch responses that report partial failure inside a 200, and
|
|
17
|
+
per-endpoint retry safety.
|
|
18
|
+
email:
|
|
19
|
+
- jim@mymat.yoga
|
|
20
|
+
executables: []
|
|
21
|
+
extensions: []
|
|
22
|
+
extra_rdoc_files: []
|
|
23
|
+
files:
|
|
24
|
+
- CHANGELOG.md
|
|
25
|
+
- LICENSE.txt
|
|
26
|
+
- README.md
|
|
27
|
+
- Rakefile
|
|
28
|
+
- lib/flodesk.rb
|
|
29
|
+
- lib/flodesk/auth.rb
|
|
30
|
+
- lib/flodesk/client.rb
|
|
31
|
+
- lib/flodesk/coercion.rb
|
|
32
|
+
- lib/flodesk/connection.rb
|
|
33
|
+
- lib/flodesk/enums.rb
|
|
34
|
+
- lib/flodesk/errors.rb
|
|
35
|
+
- lib/flodesk/instrumentation.rb
|
|
36
|
+
- lib/flodesk/objects/batch_item_error.rb
|
|
37
|
+
- lib/flodesk/objects/batch_result.rb
|
|
38
|
+
- lib/flodesk/objects/campaign.rb
|
|
39
|
+
- lib/flodesk/objects/custom_field.rb
|
|
40
|
+
- lib/flodesk/objects/page.rb
|
|
41
|
+
- lib/flodesk/objects/segment.rb
|
|
42
|
+
- lib/flodesk/objects/subscriber.rb
|
|
43
|
+
- lib/flodesk/objects/webhook.rb
|
|
44
|
+
- lib/flodesk/objects/workflow.rb
|
|
45
|
+
- lib/flodesk/rails.rb
|
|
46
|
+
- lib/flodesk/rails/railtie.rb
|
|
47
|
+
- lib/flodesk/rate_limit.rb
|
|
48
|
+
- lib/flodesk/redaction.rb
|
|
49
|
+
- lib/flodesk/resources/base.rb
|
|
50
|
+
- lib/flodesk/resources/campaigns.rb
|
|
51
|
+
- lib/flodesk/resources/custom_fields.rb
|
|
52
|
+
- lib/flodesk/resources/segments.rb
|
|
53
|
+
- lib/flodesk/resources/subscribers.rb
|
|
54
|
+
- lib/flodesk/resources/webhooks.rb
|
|
55
|
+
- lib/flodesk/resources/workflows.rb
|
|
56
|
+
- lib/flodesk/response.rb
|
|
57
|
+
- lib/flodesk/retry_policy.rb
|
|
58
|
+
- lib/flodesk/test_helpers.rb
|
|
59
|
+
- lib/flodesk/version.rb
|
|
60
|
+
- lib/flodesk/webhooks/event.rb
|
|
61
|
+
- lib/flodesk/webhooks/handler.rb
|
|
62
|
+
- lib/flodesk/webhooks/verification.rb
|
|
63
|
+
- lib/generators/flodesk/install_generator.rb
|
|
64
|
+
- lib/generators/flodesk/templates/initializer.rb.tt
|
|
65
|
+
- sig/flodesk.rbs
|
|
66
|
+
- sig/flodesk/client.rbs
|
|
67
|
+
- sig/flodesk/errors.rbs
|
|
68
|
+
- sig/flodesk/objects.rbs
|
|
69
|
+
- sig/flodesk/resources.rbs
|
|
70
|
+
- sig/flodesk/webhooks.rbs
|
|
71
|
+
homepage: https://github.com/mymat-yoga/flodesk-rb
|
|
72
|
+
licenses:
|
|
73
|
+
- MIT
|
|
74
|
+
metadata:
|
|
75
|
+
allowed_push_host: https://rubygems.org
|
|
76
|
+
homepage_uri: https://github.com/mymat-yoga/flodesk-rb
|
|
77
|
+
source_code_uri: https://github.com/mymat-yoga/flodesk-rb
|
|
78
|
+
changelog_uri: https://github.com/mymat-yoga/flodesk-rb/blob/main/CHANGELOG.md
|
|
79
|
+
rubygems_mfa_required: 'true'
|
|
80
|
+
rdoc_options: []
|
|
81
|
+
require_paths:
|
|
82
|
+
- lib
|
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: 3.2.0
|
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '0'
|
|
93
|
+
requirements: []
|
|
94
|
+
rubygems_version: 4.0.8
|
|
95
|
+
specification_version: 4
|
|
96
|
+
summary: Ruby client for the Flodesk API
|
|
97
|
+
test_files: []
|