uploadcare-ruby 4.4.3 → 5.0.0.rc1

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +7 -0
  3. data/.github/workflows/gem-push.yml +1 -1
  4. data/.github/workflows/ruby.yml +10 -13
  5. data/.gitignore +9 -0
  6. data/.rubocop.yml +95 -8
  7. data/CHANGELOG.md +71 -1
  8. data/Gemfile +23 -6
  9. data/MIGRATING_V5.md +290 -0
  10. data/README.md +422 -671
  11. data/Rakefile +5 -1
  12. data/api_examples/README.md +77 -0
  13. data/api_examples/rest_api/delete_files_storage.rb +3 -5
  14. data/api_examples/rest_api/delete_files_uuid_metadata_key.rb +3 -4
  15. data/api_examples/rest_api/delete_files_uuid_storage.rb +3 -4
  16. data/api_examples/rest_api/delete_groups_uuid.rb +3 -4
  17. data/api_examples/rest_api/delete_webhooks_unsubscribe.rb +3 -4
  18. data/api_examples/rest_api/get_addons_aws_rekognition_detect_labels_execute_status.rb +3 -6
  19. data/api_examples/rest_api/get_addons_aws_rekognition_detect_moderation_labels_execute_status.rb +3 -6
  20. data/api_examples/rest_api/get_addons_remove_bg_execute_status.rb +3 -6
  21. data/api_examples/rest_api/get_addons_uc_clamav_virus_scan_execute_status.rb +3 -6
  22. data/api_examples/rest_api/get_convert_document_status_token.rb +3 -5
  23. data/api_examples/rest_api/get_convert_document_uuid.rb +3 -5
  24. data/api_examples/rest_api/get_convert_video_status_token.rb +3 -5
  25. data/api_examples/rest_api/get_files.rb +3 -5
  26. data/api_examples/rest_api/get_files_uuid.rb +3 -5
  27. data/api_examples/rest_api/get_files_uuid_metadata.rb +3 -5
  28. data/api_examples/rest_api/get_files_uuid_metadata_key.rb +3 -5
  29. data/api_examples/rest_api/get_groups.rb +3 -5
  30. data/api_examples/rest_api/get_groups_uuid.rb +3 -5
  31. data/api_examples/rest_api/get_project.rb +3 -5
  32. data/api_examples/rest_api/get_webhooks.rb +3 -5
  33. data/api_examples/rest_api/post_addons_aws_rekognition_detect_labels_execute.rb +3 -5
  34. data/api_examples/rest_api/post_addons_aws_rekognition_detect_moderation_labels_execute.rb +3 -5
  35. data/api_examples/rest_api/post_addons_remove_bg_execute.rb +3 -5
  36. data/api_examples/rest_api/post_addons_uc_clamav_virus_scan_execute.rb +3 -5
  37. data/api_examples/rest_api/post_convert_document.rb +3 -8
  38. data/api_examples/rest_api/post_convert_video.rb +3 -10
  39. data/api_examples/rest_api/post_files_local_copy.rb +3 -6
  40. data/api_examples/rest_api/post_files_remote_copy.rb +3 -7
  41. data/api_examples/rest_api/post_webhooks.rb +3 -9
  42. data/api_examples/rest_api/put_files_storage.rb +3 -8
  43. data/api_examples/rest_api/put_files_uuid_metadata_key.rb +3 -7
  44. data/api_examples/rest_api/put_files_uuid_storage.rb +3 -5
  45. data/api_examples/rest_api/put_webhooks_id.rb +3 -11
  46. data/api_examples/support/example_helper.rb +250 -0
  47. data/api_examples/support/run_rest_example.rb +161 -0
  48. data/api_examples/support/run_upload_example.rb +88 -0
  49. data/api_examples/upload_api/get_from_url_status.rb +3 -5
  50. data/api_examples/upload_api/get_group_info.rb +3 -6
  51. data/api_examples/upload_api/get_info.rb +3 -6
  52. data/api_examples/upload_api/post_base.rb +3 -5
  53. data/api_examples/upload_api/post_from_url.rb +3 -5
  54. data/api_examples/upload_api/post_group.rb +3 -8
  55. data/api_examples/upload_api/post_multipart_complete.rb +3 -7
  56. data/api_examples/upload_api/post_multipart_start.rb +3 -7
  57. data/api_examples/upload_api/put_multipart_part.rb +4 -0
  58. data/bin/console +1 -1
  59. data/docs/release-notes-5.0.0.rc1.md +34 -0
  60. data/examples/README.md +39 -0
  61. data/examples/batch_upload.rb +54 -0
  62. data/examples/group_creation.rb +88 -0
  63. data/examples/large_file_upload.rb +88 -0
  64. data/examples/simple_upload.rb +39 -0
  65. data/examples/upload_with_progress.rb +84 -0
  66. data/examples/url_upload.rb +56 -0
  67. data/lib/uploadcare/api/rest/addons.rb +107 -0
  68. data/lib/uploadcare/api/rest/document_conversions.rb +65 -0
  69. data/lib/uploadcare/api/rest/file_metadata.rb +71 -0
  70. data/lib/uploadcare/api/rest/files.rb +112 -0
  71. data/lib/uploadcare/api/rest/groups.rb +49 -0
  72. data/lib/uploadcare/api/rest/project.rb +23 -0
  73. data/lib/uploadcare/api/rest/video_conversions.rb +52 -0
  74. data/lib/uploadcare/api/rest/webhooks.rb +74 -0
  75. data/lib/uploadcare/api/rest.rb +254 -0
  76. data/lib/uploadcare/api/upload/files.rb +313 -0
  77. data/lib/uploadcare/api/upload/groups.rb +72 -0
  78. data/lib/uploadcare/api/upload.rb +272 -0
  79. data/lib/uploadcare/client/addons_accessor.rb +85 -0
  80. data/lib/uploadcare/client/api.rb +33 -0
  81. data/lib/uploadcare/client/conversions_accessor.rb +33 -0
  82. data/lib/uploadcare/client/document_conversions_accessor.rb +41 -0
  83. data/lib/uploadcare/client/file_metadata_accessor.rb +46 -0
  84. data/lib/uploadcare/client/files_accessor.rb +82 -0
  85. data/lib/uploadcare/client/groups_accessor.rb +35 -0
  86. data/lib/uploadcare/client/project_accessor.rb +17 -0
  87. data/lib/uploadcare/client/video_conversions_accessor.rb +33 -0
  88. data/lib/uploadcare/client/webhooks_accessor.rb +42 -0
  89. data/lib/uploadcare/client.rb +127 -0
  90. data/lib/uploadcare/cname_generator.rb +68 -0
  91. data/lib/uploadcare/collections/batch_result.rb +35 -0
  92. data/lib/uploadcare/collections/paginated.rb +165 -0
  93. data/lib/uploadcare/configuration.rb +81 -0
  94. data/lib/uploadcare/exception/auth_error.rb +2 -6
  95. data/lib/uploadcare/exception/configuration_error.rb +4 -0
  96. data/lib/uploadcare/exception/conversion_error.rb +2 -6
  97. data/lib/uploadcare/exception/invalid_request_error.rb +4 -0
  98. data/lib/uploadcare/exception/multipart_upload_error.rb +4 -0
  99. data/lib/uploadcare/exception/not_found_error.rb +4 -0
  100. data/lib/uploadcare/exception/request_error.rb +2 -6
  101. data/lib/uploadcare/exception/retry_error.rb +2 -6
  102. data/lib/uploadcare/exception/throttle_error.rb +7 -11
  103. data/lib/uploadcare/exception/unknown_status_error.rb +4 -0
  104. data/lib/uploadcare/exception/upload_error.rb +4 -0
  105. data/lib/uploadcare/exception/upload_timeout_error.rb +4 -0
  106. data/lib/uploadcare/internal/authenticator.rb +101 -0
  107. data/lib/uploadcare/internal/error_handler.rb +102 -0
  108. data/lib/uploadcare/internal/signature_generator.rb +31 -0
  109. data/lib/uploadcare/internal/throttle_handler.rb +36 -0
  110. data/lib/uploadcare/internal/upload_io.rb +110 -0
  111. data/lib/uploadcare/internal/upload_params_generator.rb +86 -0
  112. data/lib/uploadcare/internal/user_agent.rb +22 -0
  113. data/lib/uploadcare/operations/multipart_upload.rb +213 -0
  114. data/lib/uploadcare/operations/upload_router.rb +162 -0
  115. data/lib/uploadcare/resources/addon_execution.rb +97 -0
  116. data/lib/uploadcare/resources/base_resource.rb +61 -0
  117. data/lib/uploadcare/resources/document_conversion.rb +81 -0
  118. data/lib/uploadcare/resources/file.rb +366 -0
  119. data/lib/uploadcare/resources/file_metadata.rb +135 -0
  120. data/lib/uploadcare/resources/group.rb +142 -0
  121. data/lib/uploadcare/resources/project.rb +26 -0
  122. data/lib/uploadcare/resources/video_conversion.rb +59 -0
  123. data/lib/uploadcare/resources/webhook.rb +85 -0
  124. data/lib/uploadcare/result.rb +85 -0
  125. data/lib/uploadcare/signed_url_generators/akamai_generator.rb +50 -51
  126. data/lib/uploadcare/signed_url_generators/base_generator.rb +15 -15
  127. data/lib/uploadcare/version.rb +7 -0
  128. data/lib/uploadcare/webhook_signature_verifier.rb +60 -0
  129. data/lib/uploadcare.rb +84 -50
  130. data/mise.toml +2 -0
  131. data/uploadcare-ruby.gemspec +8 -7
  132. metadata +102 -74
  133. data/api_examples/upload_api/put_presigned_url_x.rb +0 -8
  134. data/lib/uploadcare/api/api.rb +0 -25
  135. data/lib/uploadcare/client/addons_client.rb +0 -69
  136. data/lib/uploadcare/client/conversion/base_conversion_client.rb +0 -60
  137. data/lib/uploadcare/client/conversion/document_conversion_client.rb +0 -45
  138. data/lib/uploadcare/client/conversion/video_conversion_client.rb +0 -46
  139. data/lib/uploadcare/client/file_client.rb +0 -48
  140. data/lib/uploadcare/client/file_list_client.rb +0 -46
  141. data/lib/uploadcare/client/file_metadata_client.rb +0 -36
  142. data/lib/uploadcare/client/group_client.rb +0 -45
  143. data/lib/uploadcare/client/multipart_upload/chunks_client.rb +0 -58
  144. data/lib/uploadcare/client/multipart_upload_client.rb +0 -64
  145. data/lib/uploadcare/client/project_client.rb +0 -20
  146. data/lib/uploadcare/client/rest_client.rb +0 -77
  147. data/lib/uploadcare/client/rest_group_client.rb +0 -43
  148. data/lib/uploadcare/client/upload_client.rb +0 -46
  149. data/lib/uploadcare/client/uploader_client.rb +0 -128
  150. data/lib/uploadcare/client/webhook_client.rb +0 -49
  151. data/lib/uploadcare/concern/error_handler.rb +0 -54
  152. data/lib/uploadcare/concern/throttle_handler.rb +0 -25
  153. data/lib/uploadcare/concern/upload_error_handler.rb +0 -32
  154. data/lib/uploadcare/entity/addons.rb +0 -14
  155. data/lib/uploadcare/entity/conversion/base_converter.rb +0 -43
  156. data/lib/uploadcare/entity/conversion/document_converter.rb +0 -15
  157. data/lib/uploadcare/entity/conversion/video_converter.rb +0 -15
  158. data/lib/uploadcare/entity/decorator/paginator.rb +0 -79
  159. data/lib/uploadcare/entity/entity.rb +0 -18
  160. data/lib/uploadcare/entity/file.rb +0 -103
  161. data/lib/uploadcare/entity/file_list.rb +0 -32
  162. data/lib/uploadcare/entity/file_metadata.rb +0 -30
  163. data/lib/uploadcare/entity/group.rb +0 -49
  164. data/lib/uploadcare/entity/group_list.rb +0 -24
  165. data/lib/uploadcare/entity/project.rb +0 -13
  166. data/lib/uploadcare/entity/uploader.rb +0 -93
  167. data/lib/uploadcare/entity/webhook.rb +0 -14
  168. data/lib/uploadcare/param/authentication_header.rb +0 -37
  169. data/lib/uploadcare/param/conversion/document/processing_job_url_builder.rb +0 -39
  170. data/lib/uploadcare/param/conversion/video/processing_job_url_builder.rb +0 -64
  171. data/lib/uploadcare/param/param.rb +0 -10
  172. data/lib/uploadcare/param/secure_auth_header.rb +0 -51
  173. data/lib/uploadcare/param/simple_auth_header.rb +0 -14
  174. data/lib/uploadcare/param/upload/signature_generator.rb +0 -24
  175. data/lib/uploadcare/param/upload/upload_params_generator.rb +0 -41
  176. data/lib/uploadcare/param/user_agent.rb +0 -21
  177. data/lib/uploadcare/param/webhook_signature_verifier.rb +0 -23
  178. data/lib/uploadcare/ruby/version.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bf27040e7e061caf3e4810f1e40ab9421f0a063eee05b2338a4b1e7255524bd
4
- data.tar.gz: b41c835893fc836263ba7e354fce6427a9fbbaec26efbea485fac9874d162af1
3
+ metadata.gz: de585668a800a9c568b1c24ee4458a9347ca6d33b7ef89c395959682a0904b84
4
+ data.tar.gz: 866e8cbadbe47bae82d442d99a4dd5c4d5174fe7d18829b4d6a98658000975b0
5
5
  SHA512:
6
- metadata.gz: 810bd3ad7369ddbb2f44a932d12699c5b969bec1feb33ade6805a31a61d18afc102043ba1e61b0b53c7996956c4b6c8496a8e807598436d7325ad33c3a3bf33e
7
- data.tar.gz: ef9f05f9f586ba804de9e424ee9634abaebf8cff8a7d47be13147206fa2ff3e3adeac56f61f8ea54ccea77e36a523df100438647df01a92c0f1e0f42d5dff5b3
6
+ metadata.gz: 1f57d707ac7d812cf8a68c9328cc0ff29b81863d3f680a0be802f8c32423e9e369f78083edf035c195972abcff3a20fa2e6ea122b85f3de5a3cb496928b2831e
7
+ data.tar.gz: 0d0cca16356a961e43bfa8b04f21bbab6b166c0fdb57af4e392ba57a39ae2eb15236d3810d684e70d304562bb21c952ffba9e8a7256b277bfc449b431166a5a0
data/.env.example ADDED
@@ -0,0 +1,7 @@
1
+ # Uploadcare API credentials
2
+ # Copy this file to .env and fill in your actual keys (for local development only).
3
+ # Never commit real credentials. See MIGRATING_V5.md for v5 client-first setup details.
4
+ # Get your keys from: https://app.uploadcare.com/projects/-/api-keys/
5
+
6
+ UPLOADCARE_PUBLIC_KEY=your_public_key_here
7
+ UPLOADCARE_SECRET_KEY=your_secret_key_here
@@ -9,7 +9,7 @@ jobs:
9
9
  runs-on: ubuntu-latest
10
10
 
11
11
  steps:
12
- - uses: actions/checkout@v3
12
+ - uses: actions/checkout@v5
13
13
 
14
14
  - name: Release Gem
15
15
  if: contains(github.ref, 'refs/tags/v')
@@ -2,7 +2,7 @@
2
2
  # They are provided by a third-party and are governed by
3
3
  # separate terms of service, privacy policy, and support
4
4
  # documentation.
5
- # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
5
+ # This workflow installs Ruby, runs tests, and runs style checks in a dedicated job.
6
6
  # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
7
 
8
8
  name: Ruby
@@ -16,13 +16,12 @@ jobs:
16
16
  strategy:
17
17
  matrix:
18
18
  ruby-version:
19
- - 3.0
20
- - 3.1
21
- - 3.2
22
19
  - 3.3
20
+ - 3.4
21
+ - 4.0
23
22
 
24
23
  steps:
25
- - uses: actions/checkout@v3
24
+ - uses: actions/checkout@v5
26
25
  - name: Set up Ruby
27
26
  uses: ruby/setup-ruby@v1
28
27
  with:
@@ -30,26 +29,24 @@ jobs:
30
29
  ruby-version: ${{ matrix.ruby-version }}
31
30
  bundler-cache: true
32
31
  - name: Run tests
33
- run: bundle exec rake
32
+ # Keep test invocation on rake tasks so repository-local pre/post hooks stay centralized.
33
+ run: bundle exec rake spec
34
34
  env:
35
35
  UPLOADCARE_PUBLIC_KEY: demopublickey
36
- UPLOADCARE_SECRET_KEY: demoprivatekey
36
+ UPLOADCARE_SECRET_KEY: demosecretkey
37
37
 
38
38
  style-check:
39
39
  runs-on: ubuntu-latest
40
- continue-on-error: true
41
40
  strategy:
42
41
  matrix:
43
42
  ruby-version:
44
- - 3.3
43
+ - 4.0
45
44
  steps:
46
- - uses: actions/checkout@v3
45
+ - uses: actions/checkout@v5
47
46
  - name: Set up Ruby
48
47
  uses: ruby/setup-ruby@v1
49
48
  with:
50
49
  ruby-version: ${{ matrix.ruby-version }}
51
50
  bundler-cache: true
52
- - name: Install Rubocop
53
- run: gem install rubocop
54
51
  - name: Check codestyle
55
- run: rubocop
52
+ run: bundle exec rubocop
data/.gitignore CHANGED
@@ -18,3 +18,12 @@ Gemfile.lock
18
18
  .ruby-version
19
19
  project_files
20
20
  *.gem
21
+ .vscode/
22
+ .DS_Store
23
+ .claude/
24
+ .kiro/
25
+ .agents/
26
+
27
+ # Environment variables (API keys)
28
+ .env
29
+ .env.local
data/.rubocop.yml CHANGED
@@ -1,6 +1,18 @@
1
+ plugins:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
1
5
  AllCops:
2
6
  NewCops: enable
3
- TargetRubyVersion: 3.0
7
+ # RuboCop currently supports up to 3.5; CI still tests this gem on Ruby 4.0.
8
+ TargetRubyVersion: 3.4
9
+ SuggestExtensions: false
10
+ Exclude:
11
+ - 'examples/**/*'
12
+ - 'tmp/**/*'
13
+ - 'spec/support/**/*'
14
+ - 'api_examples/support/**/*'
15
+ - 'vendor/bundle/**/*'
4
16
 
5
17
  Layout/LineLength:
6
18
  Max: 120
@@ -10,31 +22,106 @@ Layout/LineLength:
10
22
  Lint/IneffectiveAccessModifier:
11
23
  Enabled: false
12
24
 
13
- Style/HashTransformKeys:
14
- Exclude:
15
- - 'lib/uploadcare/entity/decorator/paginator.rb'
16
- - 'lib/uploadcare/client/conversion/video_conversion_client.rb'
17
- - 'lib/uploadcare/entity/file.rb'
18
-
19
25
  Metrics/BlockLength:
26
+ Max: 30
20
27
  Exclude:
21
28
  - 'bin/'
22
29
  - 'spec/**/*'
23
30
  - 'uploadcare-ruby.gemspec'
31
+ - 'api_examples/support/**/*.rb'
32
+
33
+ Metrics/ClassLength:
34
+ Max: 200
35
+ Exclude:
36
+ - 'spec/**/*'
24
37
 
25
38
  Metrics/ModuleLength:
39
+ Max: 100
26
40
  Exclude:
27
41
  - 'spec/**/*'
42
+ - 'api_examples/support/**/*.rb'
28
43
 
29
44
  Metrics/MethodLength:
30
- Max: 20
45
+ Max: 30
46
+ Exclude:
47
+ - 'api_examples/support/**/*.rb'
48
+
49
+ Metrics/AbcSize:
50
+ Max: 28
51
+ Exclude:
52
+ - 'api_examples/support/**/*.rb'
53
+
54
+ Metrics/CyclomaticComplexity:
55
+ Max: 10
56
+ Exclude:
57
+ - 'api_examples/support/**/*.rb'
58
+
59
+ Metrics/PerceivedComplexity:
60
+ Max: 11
61
+ Exclude:
62
+ - 'api_examples/support/**/*.rb'
63
+
64
+ Metrics/ParameterLists:
65
+ Max: 8
66
+ Exclude:
67
+ - 'spec/**/*'
31
68
 
32
69
  Style/Documentation:
33
70
  Enabled: false
34
71
 
72
+ Style/ClassAndModuleChildren:
73
+ EnforcedStyle: compact
74
+
35
75
  Style/OptionalBooleanParameter:
36
76
  AllowedMethods: ['create']
37
77
 
38
78
  Style/FrozenStringLiteralComment:
39
79
  Exclude:
40
80
  - 'api_examples/**/*'
81
+
82
+ Style/ArgumentsForwarding:
83
+ Enabled: false
84
+
85
+ Gemspec/RequiredRubyVersion:
86
+ Enabled: false
87
+
88
+ RSpec/ContextWording:
89
+ Prefixes:
90
+ - when
91
+ - with
92
+ - without
93
+ - if
94
+ - unless
95
+ - for
96
+
97
+ # Kept intentionally for API-integration style specs where strict unit-style cops add noise.
98
+ RSpec/AnyInstance:
99
+ Enabled: false
100
+
101
+ RSpec/DescribedClass:
102
+ Enabled: false
103
+
104
+ RSpec/ExampleLength:
105
+ Enabled: false
106
+
107
+ RSpec/MultipleExpectations:
108
+ Enabled: false
109
+
110
+ RSpec/MultipleMemoizedHelpers:
111
+ Enabled: false
112
+
113
+ RSpec/NestedGroups:
114
+ Enabled: false
115
+
116
+ # Existing test suite uses classic doubles/spies heavily; keep these disabled until specs are migrated.
117
+ RSpec/DescribeClass:
118
+ Enabled: false
119
+
120
+ RSpec/MessageSpies:
121
+ Enabled: false
122
+
123
+ RSpec/StubbedMock:
124
+ Enabled: false
125
+
126
+ RSpec/VerifiedDoubles:
127
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,12 +1,82 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0.rc1 — 2026-04-22
4
+
5
+ This release candidate is the first public v5 cut from the rewritten codebase.
6
+
7
+ Please review [`MIGRATING_V5.md`](./MIGRATING_V5.md) before upgrading from v4.x.
8
+
9
+ ### Added
10
+
11
+ * New client-first public API centered on `Uploadcare::Client`
12
+ * Full endpoint-parity access through `client.api.rest` and `client.api.upload`
13
+ * Canonical endpoint examples for the REST API and Upload API under `api_examples/`
14
+ * Updated workflow-oriented examples under `examples/`
15
+ * Multi-account configuration support through client-scoped `Uploadcare::Configuration`
16
+ * Documented internal API surface through YARD for maintainers and integrators
17
+ * Ruby 4.0 support in the test matrix
18
+
19
+ ### Changed
20
+
21
+ * Replaced the older flatter API shape with a layered API:
22
+ * convenience layer for application code
23
+ * raw parity layer for exact endpoint access
24
+ * Replaced `dry-configurable` with a plain Ruby configuration object
25
+ * Replaced legacy HTTP and autoloading patterns with Faraday and Zeitwerk
26
+ * Standardized resource and collection return types across the convenience layer
27
+ * Reworked README, migration docs, and examples to match the current v5 API
28
+
29
+ ### Fixed
30
+
31
+ * Upload IO normalization for both path-backed files and generic readable streams
32
+ * Client/config scoping so resources do not silently fall back to the wrong account context
33
+ * Video conversion `store` parameter normalization
34
+ * Document conversion boolean option normalization to match video conversion behavior
35
+ * REST request signing so the resolved `Content-Type` is the same value used for both signing and transmission
36
+ * REST query signing to use the same parameter encoding style as request transmission
37
+ * Multipart upload retry semantics so `max_retries` means retries after the initial attempt
38
+ * Multipart upload part retries/timeouts now honor configuration (`max_upload_retries`, `upload_timeout`)
39
+ * Multipart upload worker cancellation after first parallel upload error to avoid unnecessary in-flight uploads
40
+ * Multipart upload start payload no longer sends unsupported `part_size` to `/multipart/start/`
41
+ * Upload-from-URL polling now supports exponential backoff with a configurable cap
42
+ * Example cleanup to avoid leaking temporary files and groups in the demo project
43
+ * Standalone example loading and script execution
44
+ * File metadata resource initialization now correctly assigns instance UUID
45
+ * Upload API batch uploads now avoid filename collisions without mutating caller-visible filenames
46
+ * REST authenticator now uses deterministic protocol-required digests (`MD5` body digest and `SHA1` HMAC digest)
47
+ * Upload API debug logger now avoids emitting request/response headers and bodies by default
48
+ * Thread-safe lazy memoization for client/accessor/API endpoint objects and CNAME cache internals
49
+
50
+ ### Removed
51
+
52
+ * Support for Ruby versions below `3.3`
53
+ * Legacy configuration and transport patterns that were no longer aligned with the v5 architecture
54
+ ### Risk & Rollout Notes
55
+ * Ruby support baseline is now `>= 3.3`; verify application/runtime images before upgrading.
56
+ * Recommended rc1 rollout: wire explicit `Uploadcare::Client` instances first, then migrate call sites incrementally.
57
+ * Keep rollback simple by pinning to the latest v4 release if your app depends on removed internal APIs.
58
+
59
+ ## 4.5.0 — 2025-07-25
60
+ ### Added
61
+ * **CDN Subdomain Support**: Added support for automatic subdomain generation to improve CDN performance and caching.
62
+ * New `CnameGenerator` class for generating CNAME prefixes based on public key using SHA256 hashing
63
+ * Configuration options:
64
+ * `use_subdomains` - Enable automatic subdomain generation (default: `false`)
65
+ * `cdn_base_postfix` - Base domain for subdomain generation (default: `https://ucarecd.net/`)
66
+ * `default_cdn_base` - Original CDN base URL (default: `https://ucarecdn.com/`)
67
+ * `cdn_base` - Dynamic CDN base selection based on subdomain configuration
68
+ * New `cdn_url` method for `File` and `Group` entities to get CDN URLs using configured base
69
+ * New `file_cdn_urls` method for `Group` entities to get CDN URLs of all files in a group without API requests
70
+ * New `Uploadcare::Exception::ConfigurationError` for configuration-related errors
71
+ * Ruby 3.4 support added to test matrix
72
+
3
73
  ## 4.4.3 — 2024-07-06
4
74
 
5
75
  ### Added
6
76
  * Multi page conversion parameter (`save_in_group`) added to `DocumentConverter#convert` options.
7
77
 
8
78
  ### Fixed
9
- * Fixed that signed URLs now work with ~ in the path. This also fixes signed URLs with grouped file URLs.
79
+ * Fixed that signed URLs now work with ~ in the path. This also fixes signed URLs with grouped file URLs.
10
80
 
11
81
  ## 4.4.2 — 2024-05-29
12
82
 
data/Gemfile CHANGED
@@ -2,12 +2,29 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'byebug'
6
- gem 'rake'
7
- gem 'rspec'
8
- gem 'rubocop'
9
- gem 'vcr'
10
- gem 'webmock'
5
+ group :development, :test do
6
+ # Ruby 3.4+ stopped shipping some stdlib components as default gems.
7
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.4')
8
+ gem 'base64', require: false
9
+ gem 'cgi', require: false
10
+ end
11
+
12
+ # Ruby 4.1+ removes tsort from default gems.
13
+ gem('tsort', require: false) if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('4.1')
14
+
15
+ gem 'byebug'
16
+ gem 'dotenv', '~> 3.2' # For running examples with .env file
17
+ gem 'rake'
18
+ gem 'redcarpet'
19
+ gem 'rspec'
20
+ gem 'rubocop'
21
+ gem 'rubocop-rake'
22
+ gem 'rubocop-rspec'
23
+ gem 'simplecov', require: false
24
+ gem 'vcr'
25
+ gem 'webmock'
26
+ gem 'yard'
27
+ end
11
28
 
12
29
  # Specify your gem's dependencies in uploadcare-ruby.gemspec
13
30
  gemspec
data/MIGRATING_V5.md ADDED
@@ -0,0 +1,290 @@
1
+ # Migrating From v4.x to v5
2
+
3
+ Version 5 moves the gem to a client-first API with a clearer split between the convenience layer and the endpoint-parity API.
4
+
5
+ The main migration rule is simple:
6
+
7
+ - use `Uploadcare::Client` for application code
8
+ - use `client.files`, `client.groups`, `client.uploads`, and the other domain accessors for normal workflows
9
+ - use `client.api.rest` and `client.api.upload` when you need exact Uploadcare endpoint behavior
10
+
11
+ ## What Changed
12
+
13
+ Version 5 introduces:
14
+
15
+ - a client-scoped configuration model
16
+ - first-class multi-account support
17
+ - a convenience layer that returns resources and raises typed exceptions
18
+ - a raw API layer that mirrors the REST and Upload APIs and returns `Uploadcare::Result`
19
+ - a modernized internal structure built around Zeitwerk and Faraday
20
+
21
+ Version 5 also raises the minimum supported Ruby version to `3.3`.
22
+ The CI matrix for v5 verifies `3.3`, `3.4`, and `4.0`.
23
+
24
+ If you run examples locally with `.env`, use it only for developer machines and never commit real keys.
25
+ The examples expect `UPLOADCARE_PUBLIC_KEY` and `UPLOADCARE_SECRET_KEY` to come from environment variables.
26
+
27
+ ## Recommended Migration Order
28
+
29
+ 1. Introduce explicit `Uploadcare::Client` instances in your application.
30
+ 2. Move app-facing code to `client.files`, `client.groups`, `client.uploads`, `client.project`, `client.webhooks`, `client.file_metadata`, `client.addons`, and `client.conversions`.
31
+ 3. Keep `client.api.rest` and `client.api.upload` only where you need raw endpoint parity.
32
+ 4. Audit return-type and error-handling assumptions.
33
+ 5. Remove any app code that depends on internal transport classes.
34
+
35
+ ## Configuration
36
+
37
+ ### Before
38
+
39
+ Typical v4 code relied more heavily on the process-wide configuration singleton.
40
+
41
+ ```ruby
42
+ Uploadcare.configure do |config|
43
+ config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
44
+ config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
45
+ end
46
+ ```
47
+
48
+ ### After
49
+
50
+ Global configuration still exists, but the preferred style is explicit clients.
51
+
52
+ ```ruby
53
+ client = Uploadcare::Client.new(
54
+ public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
55
+ secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
56
+ )
57
+ ```
58
+
59
+ You can also build and copy configuration objects directly:
60
+
61
+ ```ruby
62
+ base = Uploadcare::Configuration.new(
63
+ public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
64
+ secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
65
+ )
66
+
67
+ primary = Uploadcare::Client.new(config: base)
68
+ secondary = Uploadcare::Client.new(
69
+ config: base.with(public_key: "other-public-key", secret_key: "other-secret-key")
70
+ )
71
+ ```
72
+
73
+ This is the intended approach for multi-tenant Rails apps and for integrations that need more than one Uploadcare project in one process.
74
+
75
+ ## Public API Mapping
76
+
77
+ ### Uploads
78
+
79
+ ```ruby
80
+ # v4-ish
81
+ Uploadcare::Uploader.upload(object: file, store: true)
82
+
83
+ # v5
84
+ client.files.upload(file, store: true)
85
+ # or
86
+ client.uploads.upload(file, store: true)
87
+ ```
88
+
89
+ ```ruby
90
+ # v4-ish
91
+ Uploadcare::Uploader.upload(object: url, store: true)
92
+
93
+ # v5
94
+ client.files.upload_from_url(url, store: true)
95
+ ```
96
+
97
+ ```ruby
98
+ # v4-ish
99
+ Uploadcare::Uploader.upload_from_url(url: url, async: true)
100
+
101
+ # v5
102
+ client.uploads.upload_from_url(url: url, async: true)
103
+ ```
104
+
105
+ ```ruby
106
+ # v4-ish
107
+ Uploadcare::Uploader.upload_from_url_status(token: token)
108
+
109
+ # v5
110
+ client.uploads.upload_from_url_status(token: token)
111
+ ```
112
+
113
+ ### Files
114
+
115
+ ```ruby
116
+ # v4-ish
117
+ Uploadcare::File.info(uuid: uuid)
118
+
119
+ # v5
120
+ client.files.find(uuid: uuid)
121
+ ```
122
+
123
+ ```ruby
124
+ # v4-ish
125
+ Uploadcare::File.list(options: { limit: 100 })
126
+
127
+ # v5
128
+ client.files.list(limit: 100)
129
+ ```
130
+
131
+ ```ruby
132
+ # v4-ish
133
+ Uploadcare::File.batch_store(uuids: uuids)
134
+
135
+ # v5
136
+ client.files.batch_store(uuids: uuids)
137
+ ```
138
+
139
+ ```ruby
140
+ # v4-ish
141
+ Uploadcare::File.batch_delete(uuids: uuids)
142
+
143
+ # v5
144
+ client.files.batch_delete(uuids: uuids)
145
+ ```
146
+
147
+ ### Groups
148
+
149
+ ```ruby
150
+ # v4-ish
151
+ Uploadcare::Group.create(uuids: uuids)
152
+
153
+ # v5
154
+ client.groups.create(uuids: uuids)
155
+ ```
156
+
157
+ ```ruby
158
+ # v4-ish
159
+ Uploadcare::Group.info(group_id: group_id)
160
+
161
+ # v5
162
+ client.groups.find(group_id: group_id)
163
+ ```
164
+
165
+ ### Metadata
166
+
167
+ ```ruby
168
+ # v4-ish
169
+ Uploadcare::FileMetadata.update(uuid: uuid, key: "key", value: "value")
170
+
171
+ # v5
172
+ client.file_metadata.update(uuid: uuid, key: "key", value: "value")
173
+ ```
174
+
175
+ ### Webhooks
176
+
177
+ ```ruby
178
+ # v4-ish
179
+ Uploadcare::Webhook.create(target_url: url)
180
+
181
+ # v5
182
+ client.webhooks.create(target_url: url)
183
+ ```
184
+
185
+ ### Add-ons
186
+
187
+ ```ruby
188
+ # v4-ish
189
+ Uploadcare::Addons.check_remove_bg_status(request_id: request_id)
190
+
191
+ # v5
192
+ client.addons.remove_bg_status(request_id: request_id)
193
+ ```
194
+
195
+ ## Top-Level Constants
196
+
197
+ These top-level resource constants still exist:
198
+
199
+ - `Uploadcare::File`
200
+ - `Uploadcare::Group`
201
+ - `Uploadcare::Project`
202
+ - `Uploadcare::Webhook`
203
+ - `Uploadcare::FileMetadata`
204
+ - `Uploadcare::DocumentConversion`
205
+ - `Uploadcare::VideoConversion`
206
+
207
+ They remain useful for compatibility and for direct resource-oriented usage, but the main application entry point is now `Uploadcare::Client`.
208
+
209
+ ## Errors and Results
210
+
211
+ ### Convenience Layer
212
+
213
+ The convenience layer unwraps results and raises typed exceptions.
214
+
215
+ ```ruby
216
+ file = client.files.find(uuid: uuid)
217
+ ```
218
+
219
+ Typical exceptions include:
220
+
221
+ - `Uploadcare::Exception::RequestError`
222
+ - `Uploadcare::Exception::InvalidRequestError`
223
+ - `Uploadcare::Exception::NotFoundError`
224
+ - `Uploadcare::Exception::UploadError`
225
+ - `Uploadcare::Exception::MultipartUploadError`
226
+ - `Uploadcare::Exception::UploadTimeoutError`
227
+ - `Uploadcare::Exception::ThrottleError`
228
+
229
+ ### Raw API Layer
230
+
231
+ The raw API layer returns `Uploadcare::Result`.
232
+
233
+ ```ruby
234
+ result = client.api.rest.files.info(uuid: uuid)
235
+
236
+ if result.success?
237
+ puts result.success
238
+ else
239
+ warn result.error_message
240
+ end
241
+ ```
242
+
243
+ If your v4 code assumed direct hashes everywhere, decide explicitly whether it belongs on the convenience layer or the raw API layer.
244
+
245
+ ## Return Type Changes
246
+
247
+ ### Files and Groups
248
+
249
+ Convenience methods now return resource objects and paginated collections:
250
+
251
+ - `client.files.find` -> `Uploadcare::File`
252
+ - `client.files.list` -> `Uploadcare::Collections::Paginated`
253
+ - `client.groups.find` -> `Uploadcare::Group`
254
+
255
+ ### Batch Operations
256
+
257
+ Batch operations return `Uploadcare::Collections::BatchResult`.
258
+
259
+ ```ruby
260
+ result = client.files.batch_store(uuids: uuids)
261
+
262
+ result.status
263
+ result.result
264
+ result.problems
265
+ ```
266
+
267
+ ### Conversions
268
+
269
+ Document and video conversions are intentionally not perfectly symmetrical:
270
+
271
+ - `client.conversions.documents.convert` returns the API response hash
272
+ - `client.conversions.videos.convert` returns a `Uploadcare::VideoConversion` resource
273
+
274
+ Audit conversion code carefully if you rely on exact return types.
275
+
276
+ ## Internal APIs
277
+
278
+ Version 5 keeps the internal transport layer available and documented, but it is not the recommended primary surface for application code.
279
+
280
+ If you need it:
281
+
282
+ - `client.api.rest`
283
+ - `client.api.upload`
284
+
285
+ If you are wrapping the gem from another library, prefer these explicit raw API entry points over reaching into lower-level internals.
286
+
287
+ ## See Also
288
+
289
+ - [README.md](./README.md)
290
+ - [CHANGELOG.md](./CHANGELOG.md)