smswire 0.0.1.pre → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -3
  3. data/README.md +222 -9
  4. data/RELEASING.md +49 -0
  5. data/app/controllers/smswire/development_controller.rb +17 -0
  6. data/app/controllers/smswire/inbound_messages_controller.rb +9 -0
  7. data/app/controllers/smswire/inbox_controller.rb +31 -0
  8. data/app/controllers/smswire/previews_controller.rb +22 -0
  9. data/app/controllers/smswire/status_callbacks_controller.rb +8 -0
  10. data/app/controllers/smswire/webhooks_controller.rb +49 -0
  11. data/app/models/smswire/application_record.rb +5 -0
  12. data/app/models/smswire/consent.rb +71 -0
  13. data/app/models/smswire/delivery.rb +157 -0
  14. data/app/models/smswire/inbound_message.rb +25 -0
  15. data/app/views/layouts/smswire/application.html.erb +60 -0
  16. data/app/views/smswire/inbox/index.html.erb +56 -0
  17. data/app/views/smswire/previews/index.html.erb +21 -0
  18. data/app/views/smswire/previews/show.html.erb +34 -0
  19. data/config/routes.rb +10 -0
  20. data/db/migrate/20261008000000_create_smswire_deliveries.rb +47 -0
  21. data/db/migrate/20261008000001_create_smswire_consents_and_inbound_messages.rb +34 -0
  22. data/docs/SPEC.md +164 -43
  23. data/docs/guides/compliance.md +124 -0
  24. data/docs/guides/getting-started.md +154 -0
  25. data/docs/guides/migrating-from-noticed-twilio.md +105 -0
  26. data/docs/guides/migrating-from-twilio-ruby.md +146 -0
  27. data/docs/guides/writing-a-provider.md +126 -0
  28. data/lib/generators/smswire/install/install_generator.rb +44 -0
  29. data/lib/generators/smswire/install/templates/application_messenger.rb.tt +3 -0
  30. data/lib/generators/smswire/install/templates/initializer.rb.tt +35 -0
  31. data/lib/generators/smswire/messenger/messenger_generator.rb +51 -0
  32. data/lib/generators/smswire/messenger/templates/messenger.rb.tt +14 -0
  33. data/lib/generators/smswire/messenger/templates/preview.rb.tt +13 -0
  34. data/lib/generators/smswire/messenger/templates/test.rb.tt +18 -0
  35. data/lib/generators/smswire/messenger/templates/view.text.erb.tt +1 -0
  36. data/lib/generators/smswire/provider/provider_generator.rb +36 -0
  37. data/lib/generators/smswire/provider/templates/provider.rb.tt +52 -0
  38. data/lib/generators/smswire/provider/templates/test.rb.tt +29 -0
  39. data/lib/smswire/base.rb +123 -0
  40. data/lib/smswire/body_formatter.rb +14 -0
  41. data/lib/smswire/callbacks.rb +24 -0
  42. data/lib/smswire/configuration.rb +224 -0
  43. data/lib/smswire/delivery_job.rb +29 -0
  44. data/lib/smswire/engine.rb +52 -0
  45. data/lib/smswire/errors.rb +59 -0
  46. data/lib/smswire/http.rb +65 -0
  47. data/lib/smswire/inbound.rb +11 -0
  48. data/lib/smswire/inbound_handler.rb +29 -0
  49. data/lib/smswire/interceptors/allowlist.rb +36 -0
  50. data/lib/smswire/keyword_messenger.rb +12 -0
  51. data/lib/smswire/keywords.rb +51 -0
  52. data/lib/smswire/log_subscriber.rb +57 -0
  53. data/lib/smswire/message.rb +72 -0
  54. data/lib/smswire/message_delivery.rb +69 -0
  55. data/lib/smswire/noticed_delivery_method.rb +54 -0
  56. data/lib/smswire/parameterized_messenger.rb +24 -0
  57. data/lib/smswire/phone_number.rb +65 -0
  58. data/lib/smswire/pipeline.rb +114 -0
  59. data/lib/smswire/preview.rb +54 -0
  60. data/lib/smswire/provider_contract.rb +158 -0
  61. data/lib/smswire/providers/base.rb +66 -0
  62. data/lib/smswire/providers/log.rb +23 -0
  63. data/lib/smswire/providers/null.rb +12 -0
  64. data/lib/smswire/providers/telnyx.rb +178 -0
  65. data/lib/smswire/providers/test.rb +59 -0
  66. data/lib/smswire/providers/twilio.rb +167 -0
  67. data/lib/smswire/providers/vonage.rb +193 -0
  68. data/lib/smswire/providers.rb +38 -0
  69. data/lib/smswire/quiet_hours.rb +45 -0
  70. data/lib/smswire/rate_limit.rb +27 -0
  71. data/lib/smswire/receipt.rb +11 -0
  72. data/lib/smswire/recipient.rb +38 -0
  73. data/lib/smswire/result.rb +40 -0
  74. data/lib/smswire/rspec.rb +133 -0
  75. data/lib/smswire/segments.rb +81 -0
  76. data/lib/smswire/sender.rb +27 -0
  77. data/lib/smswire/status_handler.rb +25 -0
  78. data/lib/smswire/status_update.rb +8 -0
  79. data/lib/smswire/test_helper.rb +81 -0
  80. data/lib/smswire/testing.rb +72 -0
  81. data/lib/smswire/version.rb +1 -1
  82. data/lib/smswire.rb +70 -6
  83. data/smswire.gemspec +9 -5
  84. metadata +195 -10
  85. data/Gemfile +0 -7
  86. data/Rakefile +0 -8
@@ -0,0 +1,81 @@
1
+ require "active_job/test_helper"
2
+
3
+ module Smswire
4
+ # Minitest assertions for messengers.
5
+ #
6
+ # class OrderTest < ActiveSupport::TestCase
7
+ # include Smswire::TestHelper
8
+ #
9
+ # test "ships" do
10
+ # assert_sms_delivered(to: "+15551234567", messenger: OrderMessenger, action: :shipped) do
11
+ # Order.ship!(order)
12
+ # end
13
+ # end
14
+ # end
15
+ #
16
+ # Deliveries are cleared before each test. With a block, enqueued
17
+ # Smswire::DeliveryJob jobs are performed so deliver_later is covered.
18
+ module TestHelper
19
+ include ActiveJob::TestHelper
20
+
21
+ def before_setup
22
+ Smswire::Testing.clear!
23
+ super
24
+ end
25
+
26
+ def sms_deliveries
27
+ Smswire::Testing.deliveries
28
+ end
29
+
30
+ def assert_sms_delivered(count = nil, **filters, &block)
31
+ delivered =
32
+ if block
33
+ before = Smswire::Testing.deliveries.size
34
+ perform_enqueued_jobs(only: Smswire::DeliveryJob, &block)
35
+ Smswire::Testing.deliveries.drop(before)
36
+ else
37
+ Smswire::Testing.deliveries
38
+ end
39
+ matching = Smswire::Testing.match_deliveries(delivered, **filters)
40
+ described = Smswire::Testing.describe_filters(filters)
41
+
42
+ if count
43
+ assert_equal count, matching.size,
44
+ "Expected #{count} SMS#{described}, got #{matching.size} (#{delivered.size} delivered in total)"
45
+ else
46
+ assert matching.any?, "Expected an SMS#{described}, but none was delivered (#{delivered.size} in total)"
47
+ end
48
+ matching
49
+ end
50
+
51
+ def assert_no_sms_delivered(**filters, &block)
52
+ assert_sms_delivered(0, **filters, &block)
53
+ end
54
+
55
+ def assert_enqueued_sms(messenger = nil, action = nil, count: nil, params: nil, args: nil, kwargs: nil, &block)
56
+ jobs =
57
+ if block
58
+ before = enqueued_jobs.size
59
+ block.call
60
+ enqueued_jobs.drop(before)
61
+ else
62
+ enqueued_jobs
63
+ end
64
+ entries = Smswire::Testing.enqueued(jobs)
65
+ matching = Smswire::Testing.match_enqueued(entries, messenger:, action:, params:, args:, kwargs:)
66
+ label = [messenger, action].compact.join("#")
67
+ label = label.empty? ? "an SMS" : label
68
+
69
+ if count
70
+ assert_equal count, matching.size, "Expected #{count} enqueued #{label}, got #{matching.size}"
71
+ else
72
+ assert matching.any?, "Expected #{label} to be enqueued, but it was not (#{entries.size} SMS enqueued)"
73
+ end
74
+ matching
75
+ end
76
+
77
+ def assert_no_enqueued_sms(messenger = nil, action = nil, **filters, &block)
78
+ assert_enqueued_sms(messenger, action, count: 0, **filters, &block)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,72 @@
1
+ module Smswire
2
+ # Shared matching logic for Smswire::TestHelper and the RSpec matchers.
3
+ module Testing
4
+ DELIVERY_FILTERS = %i[to from body messenger action category provider].freeze
5
+
6
+ module_function
7
+
8
+ def deliveries
9
+ Providers::Test.deliveries
10
+ end
11
+
12
+ def clear!
13
+ Providers::Test.clear!
14
+ end
15
+
16
+ def match_deliveries(messages, **filters)
17
+ unknown = filters.keys - DELIVERY_FILTERS
18
+ raise ArgumentError, "Unknown filter(s): #{unknown.join(", ")}" if unknown.any?
19
+
20
+ messages.select do |message|
21
+ filters.all? do |key, expected|
22
+ actual = message.public_send(key)
23
+ case key
24
+ when :to then expected_phone?(actual, expected)
25
+ when :messenger then matches?(actual, expected.is_a?(Class) ? expected.name : expected)
26
+ else matches?(actual, expected)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ # Enqueued Smswire::DeliveryJob entries from an ActiveJob test adapter,
33
+ # deserialized into hashes with :messenger, :action, :params, :args, :kwargs.
34
+ def enqueued(jobs)
35
+ jobs.filter_map do |job|
36
+ job_class = job[:job] || job["job_class"]
37
+ next unless job_class.to_s == DeliveryJob.name
38
+
39
+ messenger, action, params, args, kwargs = ActiveJob::Arguments.deserialize(job[:args] || job["arguments"])
40
+ {messenger:, action:, params:, args:, kwargs:, queue: job[:queue], at: job[:at]}
41
+ end
42
+ end
43
+
44
+ def match_enqueued(entries, messenger: nil, action: nil, params: nil, args: nil, kwargs: nil)
45
+ entries.select do |entry|
46
+ (messenger.nil? || entry[:messenger] == (messenger.is_a?(Class) ? messenger.name : messenger.to_s)) &&
47
+ (action.nil? || entry[:action] == action.to_s) &&
48
+ (params.nil? || entry[:params] == params) &&
49
+ (args.nil? || entry[:args] == args) &&
50
+ (kwargs.nil? || entry[:kwargs] == kwargs)
51
+ end
52
+ end
53
+
54
+ def describe_filters(filters)
55
+ filters.empty? ? "" : " matching #{filters.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}"
56
+ end
57
+
58
+ def matches?(actual, expected)
59
+ case expected
60
+ when Regexp then expected.match?(actual.to_s)
61
+ when Symbol then actual.to_s == expected.to_s
62
+ else actual == expected
63
+ end
64
+ end
65
+
66
+ def expected_phone?(actual, expected)
67
+ return expected.match?(actual.to_s) if expected.is_a?(Regexp)
68
+
69
+ actual == expected || actual == PhoneNumber.normalize(expected)
70
+ end
71
+ end
72
+ end
@@ -1,3 +1,3 @@
1
1
  module Smswire
2
- VERSION = "0.0.1.pre"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/smswire.rb CHANGED
@@ -1,11 +1,75 @@
1
- require_relative "smswire/version"
1
+ require "zeitwerk"
2
+ require "active_support"
3
+ require "active_support/core_ext/object/blank"
4
+ require "active_support/core_ext/string/filters"
5
+ require "active_support/core_ext/hash/keys"
6
+ require "active_support/core_ext/class/attribute"
7
+ require "active_support/core_ext/numeric/time"
8
+ require "active_job"
9
+
10
+ loader = Zeitwerk::Loader.for_gem
11
+ loader.inflector.inflect("http" => "HTTP", "rspec" => "RSpec")
12
+ loader.ignore(
13
+ "#{__dir__}/generators",
14
+ "#{__dir__}/smswire/errors.rb",
15
+ "#{__dir__}/smswire/engine.rb",
16
+ "#{__dir__}/smswire/noticed_delivery_method.rb",
17
+ "#{__dir__}/smswire/rspec.rb"
18
+ )
19
+ loader.setup
20
+
21
+ require_relative "smswire/errors"
2
22
 
3
23
  # Smswire is the production SMS layer for Rails: messenger classes and
4
- # templates, a provider-agnostic message object, persisted deliveries with
5
- # status callbacks, consent and keyword handling, retries, development
6
- # sandboxing, previews, and test helpers.
24
+ # templates, a provider-agnostic message object, a delivery pipeline with
25
+ # typed outcomes, provider adapters, retries, and test helpers.
7
26
  #
8
- # This pre-release reserves the gem name. See docs/SPEC.md for the design.
27
+ # See docs/SPEC.md for the full design.
9
28
  module Smswire
10
- class Error < StandardError; end
29
+ class << self
30
+ def config
31
+ @config ||= Configuration.new
32
+ end
33
+
34
+ def configure
35
+ yield config
36
+ end
37
+
38
+ def reset_config!
39
+ @config = Configuration.new
40
+ end
41
+
42
+ def logger
43
+ config.logger || ActiveSupport::Logger.new($stdout)
44
+ end
45
+
46
+ # Check the credentials of +provider+ (default: the default provider)
47
+ # with one read-only API call, for boot checks and health endpoints.
48
+ def verify_credentials!(provider = nil)
49
+ Providers.resolve(provider).verify_credentials!
50
+ end
51
+
52
+ # Interceptors respond to +delivering_sms(message)+. They run after the
53
+ # recipient is normalized and before the provider is called, and may
54
+ # mutate the message or cancel it with +message.cancel!+.
55
+ def register_interceptor(interceptor)
56
+ config.interceptors << interceptor unless config.interceptors.include?(interceptor)
57
+ end
58
+
59
+ def unregister_interceptor(interceptor)
60
+ config.interceptors.delete(interceptor)
61
+ end
62
+
63
+ # Observers respond to +delivered_sms(result)+. They are called with
64
+ # every pipeline outcome except transient errors, which raise.
65
+ def register_observer(observer)
66
+ config.observers << observer unless config.observers.include?(observer)
67
+ end
68
+
69
+ def unregister_observer(observer)
70
+ config.observers.delete(observer)
71
+ end
72
+ end
11
73
  end
74
+
75
+ require_relative "smswire/engine" if defined?(Rails::Railtie)
data/smswire.gemspec CHANGED
@@ -22,17 +22,21 @@ Gem::Specification.new do |spec|
22
22
  spec.metadata["source_code_uri"] = "https://github.com/timimsms/smswire"
23
23
  spec.metadata["changelog_uri"] = "https://github.com/timimsms/smswire/blob/main/CHANGELOG.md"
24
24
  spec.metadata["bug_tracker_uri"] = "https://github.com/timimsms/smswire/issues"
25
- spec.metadata["documentation_uri"] = "https://github.com/timimsms/smswire/blob/main/docs/SPEC.md"
25
+ spec.metadata["documentation_uri"] = "https://github.com/timimsms/smswire/tree/main/docs/guides"
26
26
  spec.metadata["rubygems_mfa_required"] = "true"
27
27
 
28
28
  spec.files = Dir.chdir(__dir__) do
29
29
  `git ls-files -z`.split("\x0").reject do |f|
30
- f.start_with?("test/", "bin/", ".github/", ".gitignore")
30
+ f.start_with?("test/", "bin/", ".github/", ".gitignore", "Gemfile", "Rakefile")
31
31
  end
32
32
  end
33
33
  spec.require_paths = ["lib"]
34
34
 
35
- # Runtime dependencies arrive with the first functional release (Phase 1
36
- # of docs/SPEC.md): activesupport, activejob, activerecord, actionview,
37
- # railties, all >= 7.1. This pre-release only reserves the name.
35
+ rails_requirement = [">= 7.1", "< 9"]
36
+ spec.add_dependency "actionpack", *rails_requirement
37
+ spec.add_dependency "activejob", *rails_requirement
38
+ spec.add_dependency "activerecord", *rails_requirement
39
+ spec.add_dependency "activesupport", *rails_requirement
40
+ spec.add_dependency "railties", *rails_requirement
41
+ spec.add_dependency "zeitwerk", "~> 2.6"
38
42
  end
metadata CHANGED
@@ -1,15 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smswire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Walsh
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-10-08 00:00:00.000000000 Z
12
- dependencies: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: actionpack
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.1'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '7.1'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9'
32
+ - !ruby/object:Gem::Dependency
33
+ name: activejob
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '7.1'
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '9'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '7.1'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '9'
52
+ - !ruby/object:Gem::Dependency
53
+ name: activerecord
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '7.1'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '9'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '7.1'
69
+ - - "<"
70
+ - !ruby/object:Gem::Version
71
+ version: '9'
72
+ - !ruby/object:Gem::Dependency
73
+ name: activesupport
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '7.1'
79
+ - - "<"
80
+ - !ruby/object:Gem::Version
81
+ version: '9'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '7.1'
89
+ - - "<"
90
+ - !ruby/object:Gem::Version
91
+ version: '9'
92
+ - !ruby/object:Gem::Dependency
93
+ name: railties
94
+ requirement: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '7.1'
99
+ - - "<"
100
+ - !ruby/object:Gem::Version
101
+ version: '9'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '7.1'
109
+ - - "<"
110
+ - !ruby/object:Gem::Version
111
+ version: '9'
112
+ - !ruby/object:Gem::Dependency
113
+ name: zeitwerk
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '2.6'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '2.6'
13
126
  description: |-
14
127
  Smswire gives Rails applications Action Mailer-style messenger classes and
15
128
  templates for SMS, a provider-agnostic message object, persisted deliveries
@@ -23,12 +136,86 @@ extensions: []
23
136
  extra_rdoc_files: []
24
137
  files:
25
138
  - CHANGELOG.md
26
- - Gemfile
27
139
  - LICENSE.txt
28
140
  - README.md
29
- - Rakefile
141
+ - RELEASING.md
142
+ - app/controllers/smswire/development_controller.rb
143
+ - app/controllers/smswire/inbound_messages_controller.rb
144
+ - app/controllers/smswire/inbox_controller.rb
145
+ - app/controllers/smswire/previews_controller.rb
146
+ - app/controllers/smswire/status_callbacks_controller.rb
147
+ - app/controllers/smswire/webhooks_controller.rb
148
+ - app/models/smswire/application_record.rb
149
+ - app/models/smswire/consent.rb
150
+ - app/models/smswire/delivery.rb
151
+ - app/models/smswire/inbound_message.rb
152
+ - app/views/layouts/smswire/application.html.erb
153
+ - app/views/smswire/inbox/index.html.erb
154
+ - app/views/smswire/previews/index.html.erb
155
+ - app/views/smswire/previews/show.html.erb
156
+ - config/routes.rb
157
+ - db/migrate/20261008000000_create_smswire_deliveries.rb
158
+ - db/migrate/20261008000001_create_smswire_consents_and_inbound_messages.rb
30
159
  - docs/SPEC.md
160
+ - docs/guides/compliance.md
161
+ - docs/guides/getting-started.md
162
+ - docs/guides/migrating-from-noticed-twilio.md
163
+ - docs/guides/migrating-from-twilio-ruby.md
164
+ - docs/guides/writing-a-provider.md
165
+ - lib/generators/smswire/install/install_generator.rb
166
+ - lib/generators/smswire/install/templates/application_messenger.rb.tt
167
+ - lib/generators/smswire/install/templates/initializer.rb.tt
168
+ - lib/generators/smswire/messenger/messenger_generator.rb
169
+ - lib/generators/smswire/messenger/templates/messenger.rb.tt
170
+ - lib/generators/smswire/messenger/templates/preview.rb.tt
171
+ - lib/generators/smswire/messenger/templates/test.rb.tt
172
+ - lib/generators/smswire/messenger/templates/view.text.erb.tt
173
+ - lib/generators/smswire/provider/provider_generator.rb
174
+ - lib/generators/smswire/provider/templates/provider.rb.tt
175
+ - lib/generators/smswire/provider/templates/test.rb.tt
31
176
  - lib/smswire.rb
177
+ - lib/smswire/base.rb
178
+ - lib/smswire/body_formatter.rb
179
+ - lib/smswire/callbacks.rb
180
+ - lib/smswire/configuration.rb
181
+ - lib/smswire/delivery_job.rb
182
+ - lib/smswire/engine.rb
183
+ - lib/smswire/errors.rb
184
+ - lib/smswire/http.rb
185
+ - lib/smswire/inbound.rb
186
+ - lib/smswire/inbound_handler.rb
187
+ - lib/smswire/interceptors/allowlist.rb
188
+ - lib/smswire/keyword_messenger.rb
189
+ - lib/smswire/keywords.rb
190
+ - lib/smswire/log_subscriber.rb
191
+ - lib/smswire/message.rb
192
+ - lib/smswire/message_delivery.rb
193
+ - lib/smswire/noticed_delivery_method.rb
194
+ - lib/smswire/parameterized_messenger.rb
195
+ - lib/smswire/phone_number.rb
196
+ - lib/smswire/pipeline.rb
197
+ - lib/smswire/preview.rb
198
+ - lib/smswire/provider_contract.rb
199
+ - lib/smswire/providers.rb
200
+ - lib/smswire/providers/base.rb
201
+ - lib/smswire/providers/log.rb
202
+ - lib/smswire/providers/null.rb
203
+ - lib/smswire/providers/telnyx.rb
204
+ - lib/smswire/providers/test.rb
205
+ - lib/smswire/providers/twilio.rb
206
+ - lib/smswire/providers/vonage.rb
207
+ - lib/smswire/quiet_hours.rb
208
+ - lib/smswire/rate_limit.rb
209
+ - lib/smswire/receipt.rb
210
+ - lib/smswire/recipient.rb
211
+ - lib/smswire/result.rb
212
+ - lib/smswire/rspec.rb
213
+ - lib/smswire/segments.rb
214
+ - lib/smswire/sender.rb
215
+ - lib/smswire/status_handler.rb
216
+ - lib/smswire/status_update.rb
217
+ - lib/smswire/test_helper.rb
218
+ - lib/smswire/testing.rb
32
219
  - lib/smswire/version.rb
33
220
  - smswire.gemspec
34
221
  homepage: https://smswire.dev
@@ -39,9 +226,8 @@ metadata:
39
226
  source_code_uri: https://github.com/timimsms/smswire
40
227
  changelog_uri: https://github.com/timimsms/smswire/blob/main/CHANGELOG.md
41
228
  bug_tracker_uri: https://github.com/timimsms/smswire/issues
42
- documentation_uri: https://github.com/timimsms/smswire/blob/main/docs/SPEC.md
229
+ documentation_uri: https://github.com/timimsms/smswire/tree/main/docs/guides
43
230
  rubygems_mfa_required: 'true'
44
- post_install_message:
45
231
  rdoc_options: []
46
232
  require_paths:
47
233
  - lib
@@ -56,8 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
242
  - !ruby/object:Gem::Version
57
243
  version: '0'
58
244
  requirements: []
59
- rubygems_version: 3.5.22
60
- signing_key:
245
+ rubygems_version: 3.6.9
61
246
  specification_version: 4
62
247
  summary: The production SMS layer for Rails.
63
248
  test_files: []
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
4
-
5
- gem "rake", "~> 13.0"
6
- gem "minitest", "~> 5.25"
7
- gem "standard", "~> 1.0"
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "minitest/test_task"
3
-
4
- Minitest::TestTask.create
5
-
6
- require "standard/rake"
7
-
8
- task default: %i[test standard]