boldsign 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9fc2965681164f6e721c5d7a18b9370d1ddfd7570916cde257078b29d3be34d5
4
- data.tar.gz: 9210a75137622829403d8b6ae47dfa1f51e3f71462313b12ef076e6b240391a9
3
+ metadata.gz: cbe0865fb65380ebdee0b2a2ccca3804a3cac90639d93778cc7350ca202294d4
4
+ data.tar.gz: 93dc1c1e373d29ea4bf07af0622da0662fd5d6d0b044e317ce6e69ceb442743b
5
5
  SHA512:
6
- metadata.gz: 00ab26917b2ad3ab3af835ec58842b1fa75ba19d61254447466a5eee7b5db388f9c5800ec7807806fd737526772516f43277520ba1005d18539a8e54356f0ee8
7
- data.tar.gz: '038338c9aca83500340f85e0d6d2e6247466701739ff3606ae8bf59905f930541514e9e3130ac5296b9ee658085993c601126d84ee5e6527451b4ba1d75df1ab'
6
+ metadata.gz: 27eb15a5d89fe793cbae44f5e67ebb6b1c52eb71313e2ef677e57b004384f40e552dcebd53525c86c7ddb14d30f3fb278fe9e955aeadb39b5a2d573eb309704a
7
+ data.tar.gz: 6d11a55a16fb6f553e5136dde756baa972ebed48e0b6a5ebeac50cc3abf27b3d0ca2d2bc47103fe42ea2c3933c3a4a2c9f2d8704ed7ebd546d60c7cee69ca953
data/CHANGELOG.md CHANGED
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] — 2026-05-22
11
+
12
+ ### Changed
13
+ - Request body hash keys are now recursively converted to **camelCase** (not
14
+ PascalCase). This matches the casing used by the BoldSign OpenAPI/Swagger
15
+ schema for all request body DTOs, including nested objects like
16
+ `DocumentSigner` and `FormField`. Callers pass idiomatic snake_case (or
17
+ camelCase / PascalCase) Ruby keys and the gem emits the casing BoldSign
18
+ validates against. **Breaking** for callers that relied on the 0.3.0
19
+ PascalCase output.
20
+ - Multipart file uploads are still keyed `Files` (capital F) for the
21
+ document send endpoint; only request body field names are camelCased.
22
+ - Multipart `send_document`: single-element arrays for both `signers:` and
23
+ `files:` are now unwrapped before encoding. BoldSign's POST
24
+ `/v1/document/send` rejects `signers=[{...}]` (JSON-array string) and
25
+ `Files[]=…` (Faraday's automatic array-bracket form). The gem now emits
26
+ `signers={...}` (single JSON object) and `Files=<file>` (single FilePart)
27
+ for the one-signer/one-file case. Multi-signer / multi-file uploads are
28
+ not yet supported via this helper and raise `NotImplementedError`.
29
+
30
+ ### Removed
31
+ - `Boldsign::CaseConvert.pascalize` / `.pascalize_key`. Replaced by
32
+ `.camelize` / `.camelize_key`.
33
+
10
34
  ## [0.3.0] — 2026-05-22
11
35
 
12
36
  ### Changed
@@ -1,36 +1,39 @@
1
1
  module Boldsign
2
- # Converts arbitrary Ruby hash keys (snake_case or camelCase, Symbol or
3
- # String) to PascalCase string keys recursively, matching the casing the
4
- # BoldSign REST API expects in request bodies. Non-Hash and non-Array values
5
- # — including binary IO objects, FilePart instances, scalars, dates, etc. —
6
- # pass through untouched.
2
+ # Converts arbitrary Ruby hash keys (snake_case, camelCase, or PascalCase;
3
+ # Symbol or String) to camelCase string keys recursively, matching the
4
+ # casing the BoldSign REST API expects in request bodies. Non-Hash and
5
+ # non-Array values — including binary IO objects, FilePart instances,
6
+ # scalars, dates, etc. — pass through untouched.
7
7
  module CaseConvert
8
8
  module_function
9
9
 
10
- # Recursively PascalCase every Hash key reachable from `obj`.
10
+ # Recursively camelCase every Hash key reachable from `obj`.
11
11
  # @param obj [Object]
12
- # @return [Object] new object with the same shape and PascalCase keys
13
- def pascalize(obj)
12
+ # @return [Object] new object with the same shape and camelCase keys
13
+ def camelize(obj)
14
14
  case obj
15
15
  when Hash
16
- obj.each_with_object({}) { |(k, v), acc| acc[pascalize_key(k)] = pascalize(v) }
16
+ obj.each_with_object({}) { |(k, v), acc| acc[camelize_key(k)] = camelize(v) }
17
17
  when Array
18
- obj.map { |v| pascalize(v) }
18
+ obj.map { |v| camelize(v) }
19
19
  else
20
20
  obj
21
21
  end
22
22
  end
23
23
 
24
24
  # @param key [String, Symbol]
25
- # @return [String] PascalCase string
26
- def pascalize_key(key)
25
+ # @return [String] camelCase string
26
+ def camelize_key(key)
27
27
  str = key.to_s
28
28
  return str if str.empty?
29
29
 
30
30
  if str.include?("_")
31
- str.split("_").map { |part| capitalize_word(part) }.join
31
+ parts = str.split("_").reject(&:empty?)
32
+ return str if parts.empty?
33
+
34
+ ([parts.first.downcase] + parts.drop(1).map { |part| capitalize_word(part) }).join
32
35
  else
33
- capitalize_word(str)
36
+ lowercase_first(str)
34
37
  end
35
38
  end
36
39
 
@@ -39,5 +42,11 @@ module Boldsign
39
42
 
40
43
  str[0].upcase + str[1..]
41
44
  end
45
+
46
+ def lowercase_first(str)
47
+ return str if str.empty?
48
+
49
+ str[0].downcase + str[1..]
50
+ end
42
51
  end
43
52
  end
@@ -125,7 +125,7 @@ module Boldsign
125
125
  req.body = body
126
126
  else
127
127
  req.headers["Content-Type"] = "application/json"
128
- req.body = body.is_a?(String) ? body : JSON.generate(CaseConvert.pascalize(body))
128
+ req.body = body.is_a?(String) ? body : JSON.generate(CaseConvert.camelize(body))
129
129
  end
130
130
  end
131
131
  end
@@ -73,21 +73,36 @@ module Boldsign
73
73
 
74
74
  private
75
75
 
76
+ # BoldSign's POST /v1/document/send multipart endpoint is fussy about
77
+ # repeated/array-valued parts. Single signers must be sent as one
78
+ # multipart part whose value is the signer JSON OBJECT (not a JSON array
79
+ # containing one object). Files must be sent as a single FilePart value
80
+ # for one upload; Faraday's automatic `Files[]` bracketing breaks the
81
+ # request. For the single-signer, single-file flow (the common case) we
82
+ # unwrap one-element arrays here. Multi-signer / multi-file is not yet
83
+ # supported via this helper and will raise.
76
84
  def multipart_send_body(body, files)
77
85
  parts = body.each_with_object({}) do |(key, value), acc|
78
86
  next if value.nil?
79
87
 
80
- pascal_key = Boldsign::CaseConvert.pascalize_key(key)
81
- acc[pascal_key] = if scalar?(value)
82
- value.to_s
83
- else
84
- JSON.generate(Boldsign::CaseConvert.pascalize(value))
85
- end
88
+ camel_key = Boldsign::CaseConvert.camelize_key(key)
89
+ acc[camel_key] = encode_multipart_value(value)
86
90
  end
87
- parts["Files"] = Array(files).map { |f| file_part(f) }
91
+ files_array = Array(files)
92
+ raise NotImplementedError, "multi-file uploads are not supported yet" if files_array.size > 1
93
+
94
+ parts["Files"] = file_part(files_array.first)
88
95
  parts
89
96
  end
90
97
 
98
+ def encode_multipart_value(value)
99
+ return value.to_s if scalar?(value)
100
+ return JSON.generate(Boldsign::CaseConvert.camelize(value)) unless value.is_a?(Array)
101
+ raise NotImplementedError, "multi-element arrays are not supported in multipart bodies yet" if value.size > 1
102
+
103
+ JSON.generate(Boldsign::CaseConvert.camelize(value.first))
104
+ end
105
+
91
106
  def file_part(file)
92
107
  return file if file.is_a?(Faraday::Multipart::FilePart)
93
108
 
@@ -1,3 +1,3 @@
1
1
  module Boldsign
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boldsign
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Klein