cloudflare-ruby 0.0.1 → 0.1.2
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 +4 -4
- data/CHANGELOG.md +32 -0
- data/LICENSE +21 -0
- data/README.md +127 -3
- data/lib/cloudflare/configuration.rb +11 -0
- data/lib/cloudflare/connection.rb +52 -0
- data/lib/cloudflare/errors.rb +25 -0
- data/lib/cloudflare/realtime_kit/README.md +202 -0
- data/lib/cloudflare/realtime_kit/active_livestream_session.rb +46 -0
- data/lib/cloudflare/realtime_kit/active_session.rb +68 -0
- data/lib/cloudflare/realtime_kit/analytics.rb +57 -0
- data/lib/cloudflare/realtime_kit/app.rb +56 -0
- data/lib/cloudflare/realtime_kit/chat.rb +14 -0
- data/lib/cloudflare/realtime_kit/livestream.rb +27 -0
- data/lib/cloudflare/realtime_kit/livestream_session.rb +26 -0
- data/lib/cloudflare/realtime_kit/meeting.rb +82 -0
- data/lib/cloudflare/realtime_kit/participant.rb +40 -0
- data/lib/cloudflare/realtime_kit/preset.rb +31 -0
- data/lib/cloudflare/realtime_kit/recording.rb +85 -0
- data/lib/cloudflare/realtime_kit/session.rb +69 -0
- data/lib/cloudflare/realtime_kit/session_participant.rb +30 -0
- data/lib/cloudflare/realtime_kit/summary.rb +28 -0
- data/lib/cloudflare/realtime_kit/transcript.rb +17 -0
- data/lib/cloudflare/realtime_kit/webhook.rb +36 -0
- data/lib/cloudflare/realtime_kit.rb +23 -0
- data/lib/cloudflare/relation.rb +22 -0
- data/lib/cloudflare/resource.rb +309 -0
- data/lib/cloudflare/version.rb +3 -0
- data/lib/cloudflare-ruby.rb +1 -1
- data/lib/cloudflare.rb +34 -0
- data/sig/cloudflare/configuration.rbs +11 -0
- data/sig/cloudflare/connection.rbs +8 -0
- data/sig/cloudflare/errors.rbs +25 -0
- data/sig/cloudflare/realtime_kit.rbs +4 -0
- data/sig/cloudflare/relation.rbs +9 -0
- data/sig/cloudflare/resource.rbs +40 -0
- data/sig/cloudflare.rbs +11 -0
- data/spec/slices/realtime_kit.json +9627 -0
- metadata +70 -7
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
module Cloudflare
|
|
2
|
+
# Base class for every Cloudflare resource — Meeting, Bucket, Zone, Record,
|
|
3
|
+
# Script, etc. Provides Active-Record-flavored CRUD on top of REST endpoints,
|
|
4
|
+
# plus an `attribute` macro for explicit, source-visible attribute readers.
|
|
5
|
+
#
|
|
6
|
+
# Subclasses declare paths and attributes:
|
|
7
|
+
#
|
|
8
|
+
# class Cloudflare::RealtimeKit::Meeting < Cloudflare::Resource
|
|
9
|
+
# collection_path "/accounts/{account_id}/realtime/kit/{app_id}/meetings"
|
|
10
|
+
# member_path "/accounts/{account_id}/realtime/kit/{app_id}/meetings/{id}"
|
|
11
|
+
# scope_required :app_id
|
|
12
|
+
#
|
|
13
|
+
# attribute :id, String
|
|
14
|
+
# attribute :title, String
|
|
15
|
+
# attribute :location_hint, String, wire_name: "locationHint"
|
|
16
|
+
# end
|
|
17
|
+
class Resource
|
|
18
|
+
# Cloudflare uses two response envelope shapes:
|
|
19
|
+
# - V4 API: { result: ..., success, errors, messages } — most products
|
|
20
|
+
# - RealtimeKit (Dyte heritage): { data: ..., success }
|
|
21
|
+
ENVELOPE_KEYS = %w[result data].freeze
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
attr_reader :_collection_path, :_member_path, :_attributes
|
|
25
|
+
|
|
26
|
+
def collection_path(path = nil)
|
|
27
|
+
path ? @_collection_path = path : @_collection_path
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def member_path(path = nil)
|
|
31
|
+
path ? @_member_path = path : @_member_path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def scope_required(*keys)
|
|
35
|
+
@_explicit_scope = keys.map(&:to_sym).freeze
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def scope_params
|
|
39
|
+
((@_explicit_scope || []) + [ :account_id ]).uniq
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Mark this resource as read-only — i.e., the upstream spec exposes only
|
|
43
|
+
# GET endpoints and no POST/PATCH/PUT/DELETE. Use when a child resource
|
|
44
|
+
# surfaced by +has_many+ inherits a +.create+ from +Resource+ that would
|
|
45
|
+
# silently 404 against the spec, e.g., +SessionParticipant+. Overrides
|
|
46
|
+
# the writer methods to raise +NoMethodError+ with a spec-citing
|
|
47
|
+
# message before any HTTP call.
|
|
48
|
+
def read_only
|
|
49
|
+
@_read_only = true
|
|
50
|
+
define_singleton_method(:create) do |**|
|
|
51
|
+
raise NoMethodError, "#{name} is read-only — upstream has no POST endpoint"
|
|
52
|
+
end
|
|
53
|
+
define_method(:update) do |**|
|
|
54
|
+
raise NoMethodError, "#{self.class.name} is read-only — upstream has no PATCH endpoint"
|
|
55
|
+
end
|
|
56
|
+
define_method(:destroy) do
|
|
57
|
+
raise NoMethodError, "#{self.class.name} is read-only — upstream has no DELETE endpoint"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def read_only? = @_read_only == true
|
|
62
|
+
|
|
63
|
+
# Declare a typed attribute reader. Coerces on read for known types
|
|
64
|
+
# (Time, Integer, Float). For :boolean, also defines a `name?` predicate.
|
|
65
|
+
# Use wire_name when the on-the-wire field name differs from the
|
|
66
|
+
# snake_case Ruby identifier (e.g., camelCase fields like `locationHint`).
|
|
67
|
+
#
|
|
68
|
+
# Readers gate through +ensure_loaded!+: a stub created by +has_one+
|
|
69
|
+
# auto-fetches its attrs on the first attribute read. Action methods
|
|
70
|
+
# (+kick+, +mute+, etc.) skip the gate, so action-only flows never pay
|
|
71
|
+
# for an unwanted GET.
|
|
72
|
+
def attribute(name, type = nil, wire_name: nil)
|
|
73
|
+
key = name.to_sym
|
|
74
|
+
wire_key = wire_name&.to_s || name.to_s
|
|
75
|
+
(@_attributes ||= {})[key] = { type: type, wire_name: wire_key }
|
|
76
|
+
|
|
77
|
+
# +#id+ is special — it's used internally by +member_path+ which
|
|
78
|
+
# +reload+ depends on, so a gated reader would cause infinite
|
|
79
|
+
# recursion. Subclasses can still declare +attribute :id, String+
|
|
80
|
+
# for type documentation; we just don't override the base reader.
|
|
81
|
+
return if key == :id
|
|
82
|
+
|
|
83
|
+
define_method(name) { ensure_loaded!; coerce_attribute(@attrs[wire_key], type) }
|
|
84
|
+
define_method("#{name}?") { ensure_loaded!; !!@attrs[wire_key] } if type == :boolean
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def attributes = @_attributes ||= {}
|
|
88
|
+
|
|
89
|
+
# Records the on-the-wire field name for a request body kwarg. Use this
|
|
90
|
+
# when the request shape uses a different name than the response (e.g.,
|
|
91
|
+
# R2 sends `storageClass` but reads back `storage_class`), or when a
|
|
92
|
+
# kwarg isn't represented as an attribute at all (write-only fields).
|
|
93
|
+
def wire_kwarg(ruby_name, wire_name)
|
|
94
|
+
(@_request_wire_names ||= {})[ruby_name.to_sym] = wire_name.to_s
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Wire name used when sending a kwarg in a request body or query.
|
|
98
|
+
# Lookup order: explicit wire_kwarg → attribute's wire_name → ruby key as string.
|
|
99
|
+
def wire_name_for_request(ruby_key)
|
|
100
|
+
sym = ruby_key.to_sym
|
|
101
|
+
(@_request_wire_names || {})[sym] ||
|
|
102
|
+
attributes.dig(sym, :wire_name) ||
|
|
103
|
+
sym.to_s
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Wire name used when reading from a response. Only consults the
|
|
107
|
+
# attribute declaration (response field name).
|
|
108
|
+
def wire_name_for_response(ruby_key)
|
|
109
|
+
attributes.dig(ruby_key.to_sym, :wire_name) || ruby_key.to_s
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Translate a kwargs Hash from Ruby snake_case keys to wire-format keys
|
|
113
|
+
# for SENDING in a request body or query.
|
|
114
|
+
def to_wire_keys(hash)
|
|
115
|
+
hash.each_with_object({}) { |(k, v), out| out[wire_name_for_request(k)] = v }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Unwrap a Cloudflare response envelope (`result` for V4, `data` for
|
|
119
|
+
# RealtimeKit) and return the inner payload. Returns the response
|
|
120
|
+
# unchanged when neither envelope key is present.
|
|
121
|
+
def unwrap_envelope(response)
|
|
122
|
+
return response unless response.is_a?(Hash)
|
|
123
|
+
ENVELOPE_KEYS.each do |key|
|
|
124
|
+
return response[key] if response.key?(key) && !response[key].nil?
|
|
125
|
+
end
|
|
126
|
+
response
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Declare a nested collection reachable via REST sub-path. Returns a
|
|
130
|
+
# Relation scoped to this parent. Convention: `participants` →
|
|
131
|
+
# `Participant` (singularize + classify) in the same product namespace.
|
|
132
|
+
# Override with `class_name: "Cloudflare::Other::Klass"`.
|
|
133
|
+
def has_many(name, class_name: nil)
|
|
134
|
+
define_method(name) do
|
|
135
|
+
@relations ||= {}
|
|
136
|
+
@relations[name.to_sym] ||= Relation.new(parent: self, model: resolve_class(name, class_name: class_name, singularize: true))
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Declare a nested singleton sub-resource (no id, fixed sub-path).
|
|
141
|
+
# Returns an unloaded stub scoped to this parent. Action methods on the
|
|
142
|
+
# stub (e.g., +active_session.kick_all+) work without a fetch — they
|
|
143
|
+
# only need scope. Attribute reads (e.g., +active_session.live_participants+)
|
|
144
|
+
# auto-fetch via +ensure_loaded!+ on first access and cache thereafter.
|
|
145
|
+
#
|
|
146
|
+
# The cost trade-off is HTTP-aware: action-only flows pay nothing extra,
|
|
147
|
+
# read flows pay exactly one GET on first access.
|
|
148
|
+
def has_one(name, class_name: nil)
|
|
149
|
+
define_method(name) do
|
|
150
|
+
@singletons ||= {}
|
|
151
|
+
@singletons[name.to_sym] ||= begin
|
|
152
|
+
klass = resolve_class(name, class_name: class_name, singularize: false)
|
|
153
|
+
klass.new({}, scope: child_scope_for_nested)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# CRUD defaults. Subclasses override to add explicit kwargs.
|
|
159
|
+
|
|
160
|
+
def create(**attrs)
|
|
161
|
+
scope = extract_scope!(attrs)
|
|
162
|
+
path = interpolate(_collection_path, scope)
|
|
163
|
+
response = Connection.instance.request(:post, path, body: to_wire_keys(attrs))
|
|
164
|
+
new(response, scope: scope)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def find(id, **scope_attrs)
|
|
168
|
+
scope = build_scope(scope_attrs)
|
|
169
|
+
path = interpolate(_member_path, scope.merge(id: id))
|
|
170
|
+
response = Connection.instance.request(:get, path)
|
|
171
|
+
new(response, scope: scope)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def all(**params)
|
|
175
|
+
scope = extract_scope!(params)
|
|
176
|
+
path = interpolate(_collection_path, scope)
|
|
177
|
+
response = Connection.instance.request(:get, path, params: to_wire_keys(params))
|
|
178
|
+
items = unwrap_envelope(response)
|
|
179
|
+
Array(items).map { new(_1, scope: scope) }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
# Pulls scope params out of the kwargs hash (mutating). Defaults
|
|
184
|
+
# account_id from global config if not provided.
|
|
185
|
+
def extract_scope!(attrs)
|
|
186
|
+
scope_params.each_with_object({}) do |key, h|
|
|
187
|
+
value = attrs.delete(key) || (key == :account_id && Cloudflare.account_id)
|
|
188
|
+
raise ArgumentError, "missing required scope param: #{key}" unless value
|
|
189
|
+
h[key] = value
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def build_scope(provided)
|
|
194
|
+
scope_params.each_with_object({}) do |key, h|
|
|
195
|
+
value = provided[key] || (key == :account_id && Cloudflare.account_id)
|
|
196
|
+
raise ArgumentError, "missing required scope param: #{key}" unless value
|
|
197
|
+
h[key] = value
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def interpolate(path, values)
|
|
202
|
+
path.gsub(/\{(\w+)\}/) do
|
|
203
|
+
key = $1.to_sym
|
|
204
|
+
values[key] || raise(ArgumentError, "missing path param: #{key}")
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
attr_reader :scope
|
|
210
|
+
|
|
211
|
+
def initialize(response, scope: {})
|
|
212
|
+
@attrs = self.class.unwrap_envelope(response).then { |r| r.is_a?(Hash) ? r.transform_keys(&:to_s) : {} }
|
|
213
|
+
@scope = scope
|
|
214
|
+
@loaded = !@attrs.empty?
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Note: +#id+ is intentionally not gated through +ensure_loaded!+. It's
|
|
218
|
+
# called inside +member_path+, which +reload+ itself depends on — gating
|
|
219
|
+
# would create a fetch loop. On a not-yet-loaded stub this returns nil;
|
|
220
|
+
# in practice singletons (the only path that produces stubs) don't have
|
|
221
|
+
# +{id}+ in their member_path, so the nil is harmless during the first
|
|
222
|
+
# +reload+.
|
|
223
|
+
def id = @attrs["id"]
|
|
224
|
+
def [](key) = (ensure_loaded!; @attrs[key.to_s])
|
|
225
|
+
def to_h = (ensure_loaded!; @attrs)
|
|
226
|
+
def attributes = (ensure_loaded!; @attrs)
|
|
227
|
+
|
|
228
|
+
def update(**changes)
|
|
229
|
+
response = Connection.instance.request(:patch, member_path, body: self.class.to_wire_keys(changes))
|
|
230
|
+
set_attrs_from_response(response)
|
|
231
|
+
self
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def destroy
|
|
235
|
+
Connection.instance.request(:delete, member_path)
|
|
236
|
+
freeze
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def reload
|
|
240
|
+
response = Connection.instance.request(:get, member_path)
|
|
241
|
+
set_attrs_from_response(response)
|
|
242
|
+
self
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Replace +@attrs+ from a freshly-received response and mark the instance
|
|
246
|
+
# loaded. Subclasses that issue their own writes (e.g., +Recording#transition+,
|
|
247
|
+
# +Summary#generate+) call this so a subsequent attribute read doesn't
|
|
248
|
+
# trigger a stale re-fetch and clobber the just-written state. Public so
|
|
249
|
+
# subclasses can use it.
|
|
250
|
+
def set_attrs_from_response(response)
|
|
251
|
+
return unless response.is_a?(Hash)
|
|
252
|
+
@attrs = self.class.unwrap_envelope(response).transform_keys(&:to_s)
|
|
253
|
+
@loaded = true
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def ==(other)
|
|
257
|
+
other.is_a?(self.class) && other.id == id
|
|
258
|
+
end
|
|
259
|
+
alias_method :eql?, :==
|
|
260
|
+
|
|
261
|
+
def hash = [ self.class, id ].hash
|
|
262
|
+
|
|
263
|
+
private
|
|
264
|
+
# Auto-fetch this stub's attrs from upstream on first attribute read.
|
|
265
|
+
# No-op when already loaded. Skipped by action methods (kick, mute, etc.)
|
|
266
|
+
# which only need +@scope+, so action-only flows incur zero GETs.
|
|
267
|
+
def ensure_loaded!
|
|
268
|
+
reload unless @loaded
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def member_path
|
|
272
|
+
self.class.send(:interpolate, self.class._member_path, @scope.merge(id: id))
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
COERCERS = {
|
|
276
|
+
Time => ->(v) { v.is_a?(Time) ? v : Time.parse(v) },
|
|
277
|
+
Integer => ->(v) { Integer(v) },
|
|
278
|
+
Float => ->(v) { Float(v) }
|
|
279
|
+
}.freeze
|
|
280
|
+
private_constant :COERCERS
|
|
281
|
+
|
|
282
|
+
def coerce_attribute(value, type)
|
|
283
|
+
return nil if value.nil?
|
|
284
|
+
(COERCERS[type] || ->(v) { v }).call(value)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Resolve a nested resource class by name. `singularize: true` strips
|
|
288
|
+
# a trailing 's' (`participants` → `Participant`); `false` leaves the
|
|
289
|
+
# name as-is (`active_session` → `ActiveSession`). Override entirely
|
|
290
|
+
# via `class_name: "Cloudflare::Other::Klass"`.
|
|
291
|
+
def resolve_class(name, class_name: nil, singularize: false)
|
|
292
|
+
return Object.const_get(class_name) if class_name
|
|
293
|
+
|
|
294
|
+
product_namespace = self.class.name.split("::")[0..-2].join("::")
|
|
295
|
+
basename = name.to_s
|
|
296
|
+
basename = basename.sub(/s$/, "") if singularize
|
|
297
|
+
klass = basename.split("_").map(&:capitalize).join
|
|
298
|
+
Object.const_get("#{product_namespace}::#{klass}")
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Parent's scope + parent's id mapped to its conventional key. For
|
|
302
|
+
# `Cloudflare::RealtimeKit::Meeting` (id "mtg-1") this produces
|
|
303
|
+
# { account_id: "...", app_id: "...", meeting_id: "mtg-1" }
|
|
304
|
+
def child_scope_for_nested
|
|
305
|
+
parent_id_key = self.class.name.split("::").last.downcase + "_id"
|
|
306
|
+
@scope.merge(parent_id_key.to_sym => id)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
data/lib/cloudflare-ruby.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
require "cloudflare"
|
data/lib/cloudflare.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "faraday"
|
|
2
|
+
require "faraday/retry"
|
|
3
|
+
require "time"
|
|
4
|
+
|
|
5
|
+
require_relative "cloudflare/version"
|
|
6
|
+
|
|
7
|
+
module Cloudflare
|
|
8
|
+
autoload :Configuration, "cloudflare/configuration"
|
|
9
|
+
autoload :Connection, "cloudflare/connection"
|
|
10
|
+
autoload :Resource, "cloudflare/resource"
|
|
11
|
+
autoload :Relation, "cloudflare/relation"
|
|
12
|
+
autoload :RealtimeKit, "cloudflare/realtime_kit"
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def configure
|
|
16
|
+
yield configuration
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def configuration
|
|
20
|
+
@configuration ||= Configuration.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reset_configuration!
|
|
24
|
+
@configuration = nil
|
|
25
|
+
Connection.reset!
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def api_token = configuration.api_token
|
|
29
|
+
def account_id = configuration.account_id
|
|
30
|
+
def base_url = configuration.base_url
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
require_relative "cloudflare/errors"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Cloudflare
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
attr_reader status: Integer?
|
|
4
|
+
attr_reader body: untyped
|
|
5
|
+
|
|
6
|
+
def initialize: (?String? message, ?status: Integer?, ?body: untyped) -> void
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class AuthenticationError < Error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class NotFoundError < Error
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class ValidationError < Error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class RateLimitError < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ServerError < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
ERROR_BY_STATUS: Hash[Integer, Class]
|
|
25
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Cloudflare
|
|
2
|
+
class Resource
|
|
3
|
+
type scope_hash = Hash[Symbol, String]
|
|
4
|
+
type response = Hash[String, untyped]
|
|
5
|
+
|
|
6
|
+
attr_reader scope: scope_hash
|
|
7
|
+
|
|
8
|
+
def self._collection_path: () -> String?
|
|
9
|
+
def self._member_path: () -> String?
|
|
10
|
+
def self._attributes: () -> Hash[Symbol, untyped]
|
|
11
|
+
def self.scope_params: () -> Array[Symbol]
|
|
12
|
+
|
|
13
|
+
def self.collection_path: (?String? path) -> String?
|
|
14
|
+
def self.member_path: (?String? path) -> String?
|
|
15
|
+
def self.scope_required: (*Symbol keys) -> Array[Symbol]
|
|
16
|
+
def self.attribute: (Symbol name, ?untyped type) -> Symbol
|
|
17
|
+
def self.attributes: () -> Hash[Symbol, untyped]
|
|
18
|
+
def self.has_many: (Symbol name, ?class_name: String?) -> Symbol
|
|
19
|
+
def self.has_one: (Symbol name, ?class_name: String?) -> Symbol
|
|
20
|
+
|
|
21
|
+
def self.create: (**untyped attrs) -> Resource
|
|
22
|
+
def self.find: (String id, **untyped scope_attrs) -> Resource
|
|
23
|
+
def self.all: (**untyped params) -> Array[Resource]
|
|
24
|
+
|
|
25
|
+
def initialize: (response, ?scope: scope_hash) -> void
|
|
26
|
+
|
|
27
|
+
def id: () -> String?
|
|
28
|
+
def []: (Symbol | String key) -> untyped
|
|
29
|
+
def to_h: () -> response
|
|
30
|
+
def attributes: () -> response
|
|
31
|
+
|
|
32
|
+
def update: (**untyped changes) -> self
|
|
33
|
+
def destroy: () -> self
|
|
34
|
+
def reload: () -> self
|
|
35
|
+
|
|
36
|
+
def ==: (untyped other) -> bool
|
|
37
|
+
def eql?: (untyped other) -> bool
|
|
38
|
+
def hash: () -> Integer
|
|
39
|
+
end
|
|
40
|
+
end
|
data/sig/cloudflare.rbs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Cloudflare
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
def self.configure: () { (Configuration) -> void } -> void
|
|
5
|
+
def self.configuration: () -> Configuration
|
|
6
|
+
def self.reset_configuration!: () -> void
|
|
7
|
+
|
|
8
|
+
def self.api_token: () -> String?
|
|
9
|
+
def self.account_id: () -> String?
|
|
10
|
+
def self.base_url: () -> String
|
|
11
|
+
end
|