trycourier 6.4.3 → 6.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8b8d37f136533933d8866b7f9c65690f4a7f97c858fcfe8a59b22f9207258e3
4
- data.tar.gz: 5109857a74cebd79366d2cfe314cacebef0c42e6501cfc225e294a7c03e3b9bf
3
+ metadata.gz: b85383a5a075aec281248a33e3baeb163257dcc14a786a0faed05bafa02dd5db
4
+ data.tar.gz: f4144cce9c3b08a4b62579c54cf69a7d3234e21e61f74358ab8ac6d1702d2f57
5
5
  SHA512:
6
- metadata.gz: 999317f439a918452c23d3e626c1412afc02f921e26d5323d8c56d46d17bff8705edf5ef69c98c47eeb0247dad214e6d74e8c62241c63295da98517e58b5b1fc
7
- data.tar.gz: 28ed1d47648060561af1be5579193eb16d52c40a8d460919f046d9617e5d45ae2b34dadc16418822e8f327e442c456e1ea5cd81b3deba123ce95dcdc12346187
6
+ metadata.gz: 344f0da30f2d93dbcad8f178ac74528c4b30209b0f4c67c8fcadd3fab10a1410d313d5467dc84c267076da4ce24387fd47602087e23dcb233eade584be12350e
7
+ data.tar.gz: f10b02d48f1aee2d14d0e538eaea4125eb2099262af4cd0d5a8b391342d974f6a73094f11ad8ea50094392fae9d49de32d902804ac659218f8047e7e0a512f70
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.4.4](https://github.com/trycourier/courier-ruby/compare/v6.4.3...v6.4.4) (2026-09-03)
4
+
5
+
6
+ ### Documentation
7
+
8
+ * **api:** document the channel-block requirement on template creation ([#146](https://github.com/trycourier/courier-ruby/issues/146)) ([95749c6](https://github.com/trycourier/courier-ruby/commit/95749c6db1bd5e1b07d28d1f59970652b5cb2c49))
9
+
3
10
  ## [6.4.3](https://github.com/trycourier/courier-ruby/compare/v6.4.2...v6.4.3) (2026-08-29)
4
11
 
5
12
 
data/README.md CHANGED
@@ -9,7 +9,7 @@ Add the gem to your `Gemfile`:
9
9
  <!-- x-release-please-start-version -->
10
10
 
11
11
  ```ruby
12
- gem "trycourier", "~> 6.4.3"
12
+ gem "trycourier", "~> 6.4.4"
13
13
  ```
14
14
 
15
15
  <!-- x-release-please-end -->
@@ -10,6 +10,16 @@ module Courier
10
10
  # @return [String, nil]
11
11
  optional :channel, String
12
12
 
13
+ # @!attribute elements
14
+ # An array of elements to apply to the channel. If `raw` has not been specified,
15
+ # `elements` is `required`. Channel elements cannot nest, so these are any node
16
+ # except another channel block.
17
+ #
18
+ # @return [Array<Courier::Models::ElementalNodeNonChannel::UnionMember0, Courier::Models::ElementalNodeNonChannel::UnionMember1, Courier::Models::ElementalNodeNonChannel::UnionMember2, Courier::Models::ElementalNodeNonChannel::UnionMember3, Courier::Models::ElementalNodeNonChannel::UnionMember4, Courier::Models::ElementalNodeNonChannel::UnionMember5, Courier::Models::ElementalNodeNonChannel::UnionMember6>, nil]
19
+ optional :elements,
20
+ -> { Courier::Internal::Type::ArrayOf[union: Courier::ElementalNodeNonChannel] },
21
+ nil?: true
22
+
13
23
  # @!attribute font_size
14
24
  # Email only. Document-level base font size (CSS px, e.g. `16px`) for body content
15
25
  # — text, quote, list and action button labels. Heading styles (`h1`/`h2`/`h3`)
@@ -39,7 +49,7 @@ module Courier
39
49
  # @return [Hash{Symbol=>Object}, nil]
40
50
  optional :raw, Courier::Internal::Type::HashOf[Courier::Internal::Type::Unknown], nil?: true
41
51
 
42
- # @!method initialize(channel: nil, font_size: nil, line_height: nil, padding: nil, raw: nil)
52
+ # @!method initialize(channel: nil, elements: nil, font_size: nil, line_height: nil, padding: nil, raw: nil)
43
53
  # Some parameter documentations has been truncated, see
44
54
  # {Courier::Models::ElementalChannelNode} for more details.
45
55
  #
@@ -56,6 +66,8 @@ module Courier
56
66
  #
57
67
  # @param channel [String] The channel the contents of this element should be applied to. Can be `email`, `
58
68
  #
69
+ # @param elements [Array<Courier::Models::ElementalNodeNonChannel::UnionMember0, Courier::Models::ElementalNodeNonChannel::UnionMember1, Courier::Models::ElementalNodeNonChannel::UnionMember2, Courier::Models::ElementalNodeNonChannel::UnionMember3, Courier::Models::ElementalNodeNonChannel::UnionMember4, Courier::Models::ElementalNodeNonChannel::UnionMember5, Courier::Models::ElementalNodeNonChannel::UnionMember6>, nil] An array of elements to apply to the channel. If `raw` has not been
70
+ #
59
71
  # @param font_size [String, nil] Email only. Document-level base font size (CSS px, e.g. `16px`) for body content
60
72
  #
61
73
  # @param line_height [String, nil] Email only. Document-level line height (CSS px or unitless multiplier, e.g. `24p
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Courier
4
+ module Models
5
+ # Any Elemental node except a channel block. Channel elements are only valid as
6
+ # top-level elements, so the `elements` nested inside one can never be another
7
+ # channel. Keeping this union channel-free also keeps the schema acyclic; a
8
+ # recursive `$ref` here breaks the generated Python models.
9
+ module ElementalNodeNonChannel
10
+ extend Courier::Internal::Type::Union
11
+
12
+ # Represents a body of text to be rendered inside of the notification.
13
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember0 }
14
+
15
+ # The meta element contains information describing the notification that may be used by a particular channel or provider. One important field is the title field which will be used as the title for channels that support it.
16
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember1 }
17
+
18
+ # Used to embed an image into the notification.
19
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember2 }
20
+
21
+ # Allows the user to execute an action. Can be a button or a link.
22
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember3 }
23
+
24
+ # Renders a dividing line between elements.
25
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember4 }
26
+
27
+ # Renders a quote block.
28
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember5 }
29
+
30
+ # Raw HTML string inside an Elemental document. When rendering a message, this node is turned into output only for the email channel; for other channels it produces no blocks.
31
+ variant -> { Courier::ElementalNodeNonChannel::UnionMember6 }
32
+
33
+ class UnionMember0 < Courier::Models::ElementalTextNode
34
+ # @!attribute type
35
+ #
36
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember0::Type, nil]
37
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember0::Type }
38
+
39
+ # @!method initialize(type: nil)
40
+ # Represents a body of text to be rendered inside of the notification.
41
+ #
42
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember0::Type]
43
+
44
+ module Type
45
+ extend Courier::Internal::Type::Enum
46
+
47
+ TEXT = :text
48
+
49
+ # @!method self.values
50
+ # @return [Array<Symbol>]
51
+ end
52
+ end
53
+
54
+ class UnionMember1 < Courier::Models::ElementalMetaNode
55
+ # @!attribute type
56
+ #
57
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember1::Type, nil]
58
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember1::Type }
59
+
60
+ # @!method initialize(type: nil)
61
+ # The meta element contains information describing the notification that may be
62
+ # used by a particular channel or provider. One important field is the title field
63
+ # which will be used as the title for channels that support it.
64
+ #
65
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember1::Type]
66
+
67
+ module Type
68
+ extend Courier::Internal::Type::Enum
69
+
70
+ META = :meta
71
+
72
+ # @!method self.values
73
+ # @return [Array<Symbol>]
74
+ end
75
+ end
76
+
77
+ class UnionMember2 < Courier::Models::ElementalImageNode
78
+ # @!attribute type
79
+ #
80
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember2::Type, nil]
81
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember2::Type }
82
+
83
+ # @!method initialize(type: nil)
84
+ # Used to embed an image into the notification.
85
+ #
86
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember2::Type]
87
+
88
+ module Type
89
+ extend Courier::Internal::Type::Enum
90
+
91
+ IMAGE = :image
92
+
93
+ # @!method self.values
94
+ # @return [Array<Symbol>]
95
+ end
96
+ end
97
+
98
+ class UnionMember3 < Courier::Models::ElementalActionNode
99
+ # @!attribute type
100
+ #
101
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember3::Type, nil]
102
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember3::Type }
103
+
104
+ # @!method initialize(type: nil)
105
+ # Allows the user to execute an action. Can be a button or a link.
106
+ #
107
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember3::Type]
108
+
109
+ module Type
110
+ extend Courier::Internal::Type::Enum
111
+
112
+ ACTION = :action
113
+
114
+ # @!method self.values
115
+ # @return [Array<Symbol>]
116
+ end
117
+ end
118
+
119
+ class UnionMember4 < Courier::Models::ElementalDividerNode
120
+ # @!attribute type
121
+ #
122
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember4::Type, nil]
123
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember4::Type }
124
+
125
+ # @!method initialize(type: nil)
126
+ # Renders a dividing line between elements.
127
+ #
128
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember4::Type]
129
+
130
+ module Type
131
+ extend Courier::Internal::Type::Enum
132
+
133
+ DIVIDER = :divider
134
+
135
+ # @!method self.values
136
+ # @return [Array<Symbol>]
137
+ end
138
+ end
139
+
140
+ class UnionMember5 < Courier::Models::ElementalQuoteNode
141
+ # @!attribute type
142
+ #
143
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember5::Type, nil]
144
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember5::Type }
145
+
146
+ # @!method initialize(type: nil)
147
+ # Renders a quote block.
148
+ #
149
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember5::Type]
150
+
151
+ module Type
152
+ extend Courier::Internal::Type::Enum
153
+
154
+ QUOTE = :quote
155
+
156
+ # @!method self.values
157
+ # @return [Array<Symbol>]
158
+ end
159
+ end
160
+
161
+ class UnionMember6 < Courier::Models::ElementalHTMLNode
162
+ # @!attribute type
163
+ #
164
+ # @return [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember6::Type, nil]
165
+ optional :type, enum: -> { Courier::ElementalNodeNonChannel::UnionMember6::Type }
166
+
167
+ # @!method initialize(type: nil)
168
+ # Raw HTML string inside an Elemental document. When rendering a message, this
169
+ # node is turned into output only for the email channel; for other channels it
170
+ # produces no blocks.
171
+ #
172
+ # @param type [Symbol, Courier::Models::ElementalNodeNonChannel::UnionMember6::Type]
173
+
174
+ module Type
175
+ extend Courier::Internal::Type::Enum
176
+
177
+ HTML = :html
178
+
179
+ # @!method self.values
180
+ # @return [Array<Symbol>]
181
+ end
182
+ end
183
+
184
+ # @!method self.variants
185
+ # @return [Array(Courier::Models::ElementalNodeNonChannel::UnionMember0, Courier::Models::ElementalNodeNonChannel::UnionMember1, Courier::Models::ElementalNodeNonChannel::UnionMember2, Courier::Models::ElementalNodeNonChannel::UnionMember3, Courier::Models::ElementalNodeNonChannel::UnionMember4, Courier::Models::ElementalNodeNonChannel::UnionMember5, Courier::Models::ElementalNodeNonChannel::UnionMember6)]
186
+ end
187
+ end
188
+ end
@@ -21,9 +21,12 @@ module Courier
21
21
  # Some parameter documentations has been truncated, see
22
22
  # {Courier::Models::NotificationTemplateUpdateRequest} for more details.
23
23
  #
24
- # Request body for replacing a notification template. Same shape as create. All
25
- # fields required (PUT = full replacement), except `alias`, whose omission means
26
- # "leave the existing aliases alone".
24
+ # Request body for replacing a notification template. All fields are required,
25
+ # since `PUT` is a full replacement, except `alias`, whose omission leaves the
26
+ # existing aliases in place. Unlike `NotificationTemplateCreateRequest`,
27
+ # `notification.content` is not required to place its elements inside a channel
28
+ # block: the requirement applies to creation only, so templates already stored
29
+ # without one stay editable.
27
30
  #
28
31
  # @param notification [Courier::Models::NotificationTemplateWritePayload] Template fields accepted in POST and PUT request bodies, nested under a `notific
29
32
  #
@@ -227,6 +227,8 @@ module Courier
227
227
 
228
228
  ElementalNode = Courier::Models::ElementalNode
229
229
 
230
+ ElementalNodeNonChannel = Courier::Models::ElementalNodeNonChannel
231
+
230
232
  ElementalQuoteNode = Courier::Models::ElementalQuoteNode
231
233
 
232
234
  ElementalQuoteNodeWithType = Courier::Models::ElementalQuoteNodeWithType
@@ -12,6 +12,13 @@ module Courier
12
12
  # Create a notification template scoped to this journey. Defaults to `DRAFT`
13
13
  # state; pass `state: "PUBLISHED"` to publish on create.
14
14
  #
15
+ # The content tree must contain exactly one channel block whose `channel` matches
16
+ # the `channel` on the request — a journey-scoped template carries a single
17
+ # channel. Top-level elements, or a block for a different channel, return `400`.
18
+ # The template designer renders only the channel block matching the tab it draws,
19
+ # so content stored without one cannot be opened. An empty `elements` array is
20
+ # accepted.
21
+ #
15
22
  # @overload create(template_id, channel:, notification:, provider_key: nil, state: nil, idempotency_key: nil, x_idempotency_expiration: nil, request_options: {})
16
23
  #
17
24
  # @param template_id [String] Path param: Journey id
@@ -16,6 +16,16 @@ module Courier
16
16
  # Create a notification template. Requires all fields in the notification object.
17
17
  # Templates are created in draft state by default.
18
18
  #
19
+ # Content must place its elements inside a channel block —
20
+ # `{ "type": "channel", "channel": "email", "elements": [...] }` — or the request
21
+ # returns `400`. The template designer renders only the channel block matching the
22
+ # tab it draws, so content stored without one cannot be opened. An empty
23
+ # `elements` array is accepted, and the requirement applies to creation only:
24
+ # `PUT /notifications/{id}` still accepts unwrapped content. Note this endpoint
25
+ # takes versioned content only — the `{ title, body }` shorthand accepted by
26
+ # `/send` is rejected here with an `invalid_request_error` on
27
+ # `notification.content.version`.
28
+ #
19
29
  # @overload create(notification:, state: nil, idempotency_key: nil, x_idempotency_expiration: nil, request_options: {})
20
30
  #
21
31
  # @param notification [Courier::Models::NotificationTemplateWritePayload] Body param: Template fields accepted in POST and PUT request bodies, nested unde
@@ -135,6 +135,16 @@ module Courier
135
135
  # Creates or updates a notification template scoped to one tenant, letting a
136
136
  # tenant override the content the workspace template would send.
137
137
  #
138
+ # This is an upsert: it creates when the tenant has no template under
139
+ # `template_id`, and updates when it does. On the create half, content must place
140
+ # its elements inside a channel block —
141
+ # `{ "type": "channel", "channel": "email", "elements": [...] }` — or the request
142
+ # returns `400`. The template designer renders only the channel block matching the
143
+ # tab it draws, so content stored without one cannot be opened. An empty
144
+ # `elements` array is accepted, as is the `{ title, body }` shorthand, which has
145
+ # no elements to wrap. Updates are not checked, so tenant templates already stored
146
+ # without a wrapper stay editable.
147
+ #
138
148
  # @overload replace(template_id, tenant_id:, template:, published: nil, request_options: {})
139
149
  #
140
150
  # @param template_id [String] Path param: Id of the template to be created or updated.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Courier
4
- VERSION = "6.4.3"
4
+ VERSION = "6.4.4"
5
5
  end
data/lib/courier.rb CHANGED
@@ -189,6 +189,7 @@ require_relative "courier/models/elemental_html_node_with_type"
189
189
  require_relative "courier/models/elemental_image_node_with_type"
190
190
  require_relative "courier/models/elemental_meta_node_with_type"
191
191
  require_relative "courier/models/elemental_node"
192
+ require_relative "courier/models/elemental_node_non_channel"
192
193
  require_relative "courier/models/elemental_quote_node_with_type"
193
194
  require_relative "courier/models/elemental_text_node_with_type"
194
195
  require_relative "courier/models/element_with_checksums"
@@ -16,6 +16,28 @@ module Courier
16
16
  sig { params(channel: String).void }
17
17
  attr_writer :channel
18
18
 
19
+ # An array of elements to apply to the channel. If `raw` has not been specified,
20
+ # `elements` is `required`. Channel elements cannot nest, so these are any node
21
+ # except another channel block.
22
+ sig do
23
+ returns(
24
+ T.nilable(
25
+ T::Array[
26
+ T.any(
27
+ Courier::ElementalNodeNonChannel::UnionMember0,
28
+ Courier::ElementalNodeNonChannel::UnionMember1,
29
+ Courier::ElementalNodeNonChannel::UnionMember2,
30
+ Courier::ElementalNodeNonChannel::UnionMember3,
31
+ Courier::ElementalNodeNonChannel::UnionMember4,
32
+ Courier::ElementalNodeNonChannel::UnionMember5,
33
+ Courier::ElementalNodeNonChannel::UnionMember6
34
+ )
35
+ ]
36
+ )
37
+ )
38
+ end
39
+ attr_accessor :elements
40
+
19
41
  # Email only. Document-level base font size (CSS px, e.g. `16px`) for body content
20
42
  # — text, quote, list and action button labels. Heading styles (`h1`/`h2`/`h3`)
21
43
  # and `subtext` keep their preset sizes.
@@ -50,6 +72,20 @@ module Courier
50
72
  sig do
51
73
  params(
52
74
  channel: String,
75
+ elements:
76
+ T.nilable(
77
+ T::Array[
78
+ T.any(
79
+ Courier::ElementalNodeNonChannel::UnionMember0::OrHash,
80
+ Courier::ElementalNodeNonChannel::UnionMember1::OrHash,
81
+ Courier::ElementalNodeNonChannel::UnionMember2::OrHash,
82
+ Courier::ElementalNodeNonChannel::UnionMember3::OrHash,
83
+ Courier::ElementalNodeNonChannel::UnionMember4::OrHash,
84
+ Courier::ElementalNodeNonChannel::UnionMember5::OrHash,
85
+ Courier::ElementalNodeNonChannel::UnionMember6::OrHash
86
+ )
87
+ ]
88
+ ),
53
89
  font_size: T.nilable(String),
54
90
  line_height: T.nilable(String),
55
91
  padding: T.nilable(String),
@@ -60,6 +96,10 @@ module Courier
60
96
  # The channel the contents of this element should be applied to. Can be `email`,
61
97
  # `push`, `direct_message`, `sms` or a provider such as slack
62
98
  channel: nil,
99
+ # An array of elements to apply to the channel. If `raw` has not been specified,
100
+ # `elements` is `required`. Channel elements cannot nest, so these are any node
101
+ # except another channel block.
102
+ elements: nil,
63
103
  # Email only. Document-level base font size (CSS px, e.g. `16px`) for body content
64
104
  # — text, quote, list and action button labels. Heading styles (`h1`/`h2`/`h3`)
65
105
  # and `subtext` keep their preset sizes.
@@ -80,6 +120,20 @@ module Courier
80
120
  override.returns(
81
121
  {
82
122
  channel: String,
123
+ elements:
124
+ T.nilable(
125
+ T::Array[
126
+ T.any(
127
+ Courier::ElementalNodeNonChannel::UnionMember0,
128
+ Courier::ElementalNodeNonChannel::UnionMember1,
129
+ Courier::ElementalNodeNonChannel::UnionMember2,
130
+ Courier::ElementalNodeNonChannel::UnionMember3,
131
+ Courier::ElementalNodeNonChannel::UnionMember4,
132
+ Courier::ElementalNodeNonChannel::UnionMember5,
133
+ Courier::ElementalNodeNonChannel::UnionMember6
134
+ )
135
+ ]
136
+ ),
83
137
  font_size: T.nilable(String),
84
138
  line_height: T.nilable(String),
85
139
  padding: T.nilable(String),