petstore_api_client 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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +33 -0
  3. data/.env.example +50 -0
  4. data/.github/CODEOWNERS +36 -0
  5. data/.github/workflows/ci.yml +157 -0
  6. data/.ruby-version +1 -0
  7. data/CONTRIBUTORS.md +39 -0
  8. data/LICENSE +21 -0
  9. data/README.md +684 -0
  10. data/Rakefile +12 -0
  11. data/lib/petstore_api_client/api_client.rb +60 -0
  12. data/lib/petstore_api_client/authentication/api_key.rb +107 -0
  13. data/lib/petstore_api_client/authentication/base.rb +113 -0
  14. data/lib/petstore_api_client/authentication/composite.rb +178 -0
  15. data/lib/petstore_api_client/authentication/none.rb +42 -0
  16. data/lib/petstore_api_client/authentication/oauth2.rb +305 -0
  17. data/lib/petstore_api_client/client.rb +87 -0
  18. data/lib/petstore_api_client/clients/concerns/pagination.rb +124 -0
  19. data/lib/petstore_api_client/clients/concerns/resource_operations.rb +121 -0
  20. data/lib/petstore_api_client/clients/pet_client.rb +119 -0
  21. data/lib/petstore_api_client/clients/store_client.rb +37 -0
  22. data/lib/petstore_api_client/configuration.rb +318 -0
  23. data/lib/petstore_api_client/connection.rb +55 -0
  24. data/lib/petstore_api_client/errors.rb +70 -0
  25. data/lib/petstore_api_client/middleware/authentication.rb +44 -0
  26. data/lib/petstore_api_client/models/api_response.rb +31 -0
  27. data/lib/petstore_api_client/models/base.rb +60 -0
  28. data/lib/petstore_api_client/models/category.rb +17 -0
  29. data/lib/petstore_api_client/models/named_entity.rb +36 -0
  30. data/lib/petstore_api_client/models/order.rb +55 -0
  31. data/lib/petstore_api_client/models/pet.rb +225 -0
  32. data/lib/petstore_api_client/models/tag.rb +20 -0
  33. data/lib/petstore_api_client/paginated_collection.rb +133 -0
  34. data/lib/petstore_api_client/request.rb +225 -0
  35. data/lib/petstore_api_client/response.rb +193 -0
  36. data/lib/petstore_api_client/validators/array_presence_validator.rb +15 -0
  37. data/lib/petstore_api_client/validators/enum_validator.rb +17 -0
  38. data/lib/petstore_api_client/version.rb +5 -0
  39. data/lib/petstore_api_client.rb +55 -0
  40. metadata +252 -0
data/README.md ADDED
@@ -0,0 +1,684 @@
1
+ # ๐Ÿพ Petstore API Client
2
+
3
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-ruby.svg?style=flat-square&logo=ruby&logoColor=white)](https://www.ruby-lang.org/)
4
+ [![Tests](https://img.shields.io/badge/tests-454%20passing-success.svg?style=flat-square)](https://rspec.info/)
5
+ [![Coverage](https://img.shields.io/badge/coverage-96.91%25-brightgreen.svg?style=flat-square)](https://github.com/hammadxcm/petstore-api-client)
6
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
7
+ [![GitHub](https://img.shields.io/badge/GitHub-hammadxcm-181717.svg?style=flat-square&logo=github)](https://github.com/hammadxcm)
8
+
9
+ > Production-ready Ruby client for the Swagger Petstore API with OAuth2 support, automatic retries, and comprehensive validation.
10
+ >
11
+ > **Author:** Hammad Khan ([@hammadxcm](https://github.com/hammadxcm))
12
+ >
13
+ > **Note:** All architecture, business logic, implementation, and test coverage were developed by me from scratch. AI tools were used solely to enhance documentation and code comments.
14
+
15
+ ## ๐Ÿš€ Quick Start
16
+
17
+ ```ruby
18
+ gem install petstore_api_client
19
+
20
+ require 'petstore_api_client'
21
+
22
+ # Create client
23
+ client = PetstoreApiClient::ApiClient.new
24
+
25
+ # Create a pet
26
+ pet = client.create_pet(
27
+ name: "Fluffy",
28
+ photo_urls: ["https://example.com/fluffy.jpg"],
29
+ status: "available"
30
+ )
31
+ ```
32
+
33
+ ## โœจ Features
34
+
35
+ | Feature | Description |
36
+ |----------------------------|--------------------------------------------|
37
+ | ๐Ÿ” **Dual Authentication** | API Key & OAuth2 (Client Credentials) |
38
+ | ๐Ÿ”„ **Auto Retry** | Exponential backoff for transient failures |
39
+ | โšก **Rate Limiting** | Smart handling with retry-after support |
40
+ | ๐Ÿ“„ **Pagination** | Flexible page/offset navigation |
41
+ | โœ… **Validation** | Pre-request data validation |
42
+ | ๐Ÿ›ก๏ธ **Error Handling** | 7 custom exception types |
43
+ | ๐Ÿ“Š **Test Coverage** | 96.91% coverage, 454 passing tests |
44
+ | ๐ŸŽฏ **SOLID Design** | Production-ready architecture |
45
+
46
+ ## ๐Ÿ“ฆ Installation
47
+
48
+ ```bash
49
+ # Gemfile
50
+ gem 'petstore_api_client'
51
+
52
+ # Install
53
+ bundle install
54
+ ```
55
+
56
+ ## ๐Ÿ” Authentication
57
+
58
+ The client supports **multiple authentication strategies** with feature flags:
59
+
60
+ ```mermaid
61
+ graph TD
62
+ A[Configure Auth Strategy] --> B{Which Strategy?}
63
+ B -->|:none| C[No Authentication]
64
+ B -->|:api_key| D[API Key Only]
65
+ B -->|:oauth2| E[OAuth2 Only]
66
+ B -->|:both| F[API Key + OAuth2]
67
+
68
+ D --> G[Add api_key Header]
69
+ E --> H[Fetch OAuth2 Token]
70
+ H --> I[Add Authorization: Bearer]
71
+ F --> J[Add Both Headers]
72
+
73
+ style B fill:#e3f2fd
74
+ style D fill:#fff3e0
75
+ style E fill:#c8e6c9
76
+ style F fill:#f3e5f5
77
+ ```
78
+
79
+ ### ๐Ÿ”‘ API Key Authentication
80
+
81
+ ```ruby
82
+ client = PetstoreApiClient::ApiClient.new
83
+ client.configure do |config|
84
+ config.auth_strategy = :api_key # Default
85
+ config.api_key = "special-key"
86
+ end
87
+ ```
88
+
89
+ **From Environment:**
90
+ ```bash
91
+ export PETSTORE_API_KEY="your-key"
92
+ ```
93
+ ```ruby
94
+ config.api_key = :from_env # Loads from PETSTORE_API_KEY
95
+ ```
96
+
97
+ ### ๐ŸŽซ OAuth2 Authentication
98
+
99
+ ```ruby
100
+ client.configure do |config|
101
+ config.auth_strategy = :oauth2
102
+ config.oauth2_client_id = "my-client-id"
103
+ config.oauth2_client_secret = "my-secret"
104
+ config.oauth2_scope = "read:pets write:pets" # Optional
105
+ end
106
+ ```
107
+
108
+ **OAuth2 Flow:**
109
+ ```mermaid
110
+ sequenceDiagram
111
+ participant App as Your App
112
+ participant Client as API Client
113
+ participant Auth as OAuth2 Strategy
114
+ participant Token as Token Server
115
+ participant API as Petstore API
116
+
117
+ App->>Client: create_pet(data)
118
+ Client->>Auth: apply(request)
119
+
120
+ alt Token Missing/Expired
121
+ Auth->>Token: POST /oauth/token
122
+ Token-->>Auth: access_token + expires_in
123
+ Auth->>Auth: Cache token
124
+ end
125
+
126
+ Auth->>Auth: Add Authorization: Bearer {token}
127
+ Client->>API: POST /pet (with Bearer token)
128
+ API-->>Client: 200 OK + Pet data
129
+ Client-->>App: Pet object
130
+ ```
131
+
132
+ **Environment Variables:**
133
+ ```bash
134
+ export PETSTORE_OAUTH2_CLIENT_ID="my-client-id"
135
+ export PETSTORE_OAUTH2_CLIENT_SECRET="my-secret"
136
+ export PETSTORE_OAUTH2_TOKEN_URL="https://custom.com/token" # Optional
137
+ export PETSTORE_OAUTH2_SCOPE="read:pets write:pets" # Optional
138
+ ```
139
+
140
+ ### ๐Ÿ”€ Dual Authentication (Both)
141
+
142
+ Send **both** API Key and OAuth2 headers simultaneously:
143
+
144
+ ```ruby
145
+ client.configure do |config|
146
+ config.auth_strategy = :both
147
+ config.api_key = "special-key"
148
+ config.oauth2_client_id = "client-id"
149
+ config.oauth2_client_secret = "secret"
150
+ end
151
+
152
+ # Requests will include:
153
+ # - api_key: special-key
154
+ # - Authorization: Bearer {access_token}
155
+ ```
156
+
157
+ ### ๐Ÿšซ No Authentication
158
+
159
+ ```ruby
160
+ config.auth_strategy = :none # No auth headers
161
+ ```
162
+
163
+ ### ๐Ÿ”’ Security Features
164
+
165
+ | Feature | Description |
166
+ |-----------------------------|----------------------------------------------|
167
+ | โœ… **Credential Validation** | Format & length checks |
168
+ | โœ… **HTTPS Warnings** | Alerts for insecure connections |
169
+ | โœ… **Secure Logging** | API keys masked in output (e.g., `spec****`) |
170
+ | โœ… **Token Auto-Refresh** | OAuth2 tokens refreshed 60s before expiry |
171
+ | โœ… **Thread-Safe** | Mutex-protected token management |
172
+
173
+ ## โš™๏ธ Configuration
174
+
175
+ <details>
176
+ <summary><b>๐Ÿ“‹ All Configuration Options</b></summary>
177
+
178
+ | Option | Type | Default | Description |
179
+ |------------------------|---------|-------------------------------------------|-----------------------------------------|
180
+ | `base_url` | String | `https://petstore.swagger.io/v2` | API endpoint |
181
+ | `auth_strategy` | Symbol | `:api_key` | `:none`, `:api_key`, `:oauth2`, `:both` |
182
+ | `api_key` | String | `nil` | API key for authentication |
183
+ | `oauth2_client_id` | String | `nil` | OAuth2 client ID |
184
+ | `oauth2_client_secret` | String | `nil` | OAuth2 client secret |
185
+ | `oauth2_token_url` | String | `https://petstore.swagger.io/oauth/token` | OAuth2 token endpoint |
186
+ | `oauth2_scope` | String | `nil` | OAuth2 scope |
187
+ | `timeout` | Integer | `30` | Request timeout (seconds) |
188
+ | `open_timeout` | Integer | `10` | Connection timeout (seconds) |
189
+ | `retry_enabled` | Boolean | `true` | Enable auto-retry |
190
+ | `max_retries` | Integer | `2` | Retry attempts |
191
+ | `default_page_size` | Integer | `25` | Pagination page size |
192
+ | `max_page_size` | Integer | `100` | Max pagination size |
193
+
194
+ </details>
195
+
196
+ ```ruby
197
+ client = PetstoreApiClient::ApiClient.new
198
+ client.configure do |config|
199
+ config.timeout = 60
200
+ config.retry_enabled = true
201
+ config.max_retries = 3
202
+ end
203
+ ```
204
+
205
+ ## ๐Ÿ”„ Auto-Retry & Rate Limiting
206
+
207
+ ```mermaid
208
+ flowchart LR
209
+ A[Request] --> B{Success?}
210
+ B -->|2xx| C[โœ… Return]
211
+ B -->|429/5xx| D{Retries<br/>Left?}
212
+ B -->|4xx| E[โŒ Error]
213
+
214
+ D -->|Yes| F[Wait +<br/>Backoff]
215
+ D -->|No| G[โŒ Raise<br/>Error]
216
+
217
+ F --> A
218
+
219
+ style C fill:#c8e6c9
220
+ style E fill:#ffcdd2
221
+ style G fill:#ffcdd2
222
+ style F fill:#fff9c4
223
+ ```
224
+
225
+ **Handles:**
226
+ - ๐Ÿ” Network failures
227
+ - โฑ๏ธ Timeouts
228
+ - ๐Ÿšฆ Rate limits (429)
229
+ - ๐Ÿ”ง Server errors (500, 502, 503, 504)
230
+
231
+ ```ruby
232
+ begin
233
+ pet = client.get_pet(123)
234
+ rescue PetstoreApiClient::RateLimitError => e
235
+ puts "Retry after: #{e.retry_after}s"
236
+ end
237
+ ```
238
+
239
+ ## ๐Ÿ“š Usage Examples
240
+
241
+ ### ๐Ÿ• Pet Management
242
+
243
+ ```ruby
244
+ # Create
245
+ pet = client.create_pet(
246
+ name: "Max",
247
+ photo_urls: ["https://example.com/max.jpg"],
248
+ category: { id: 1, name: "Dogs" },
249
+ tags: [{ id: 1, name: "friendly" }],
250
+ status: "available" # available | pending | sold
251
+ )
252
+
253
+ # Read
254
+ pet = client.get_pet(123)
255
+
256
+ # Update
257
+ updated = client.update_pet(
258
+ id: 123,
259
+ name: "Max Updated",
260
+ photo_urls: ["https://example.com/max-new.jpg"],
261
+ status: "sold"
262
+ )
263
+
264
+ # Delete
265
+ client.delete_pet(123)
266
+
267
+ # Find by status (with pagination)
268
+ pets = client.pets.find_by_status("available", page: 1, per_page: 10)
269
+
270
+ # Find by tags
271
+ pets = client.pets.find_by_tags(["friendly", "vaccinated"])
272
+ ```
273
+
274
+ ### ๐Ÿ›’ Store Orders
275
+
276
+ ```ruby
277
+ # Create order
278
+ order = client.create_order(
279
+ pet_id: 123,
280
+ quantity: 2,
281
+ status: "placed", # placed | approved | delivered
282
+ ship_date: DateTime.now + 7
283
+ )
284
+
285
+ # Get order
286
+ order = client.get_order(987)
287
+
288
+ # Delete order
289
+ client.delete_order(987)
290
+ ```
291
+
292
+ ### ๐Ÿ“„ Pagination
293
+
294
+ ```ruby
295
+ pets = client.pets.find_by_status("available", page: 1, per_page: 25)
296
+
297
+ # Navigation
298
+ puts "Page #{pets.page} of #{pets.total_pages}"
299
+ puts "Showing #{pets.count} of #{pets.total_count}"
300
+
301
+ pets.next_page? # => true
302
+ pets.prev_page? # => false
303
+ pets.first_page? # => true
304
+ pets.last_page? # => false
305
+
306
+ # Iterate
307
+ pets.each { |pet| puts pet.name }
308
+ pets.map(&:id)
309
+ ```
310
+
311
+ ## ๐Ÿ›ก๏ธ Error Handling
312
+
313
+ ```mermaid
314
+ graph TD
315
+ A[PetstoreApiClient::Error] --> B[ValidationError<br/>โš ๏ธ Pre-request]
316
+ A --> C[ConfigurationError<br/>โš™๏ธ Config invalid]
317
+ A --> D[AuthenticationError<br/>๐Ÿ”’ Auth failed]
318
+ A --> E[NotFoundError<br/>โ“ 404]
319
+ A --> F[InvalidInputError<br/>โš ๏ธ 400/405]
320
+ A --> G[InvalidOrderError<br/>๐Ÿ“ฆ 400 order]
321
+ A --> H[RateLimitError<br/>โฑ๏ธ 429]
322
+ A --> I[ConnectionError<br/>๐ŸŒ Network]
323
+ A --> J[ApiError<br/>๐Ÿ”ง 5xx]
324
+
325
+ style A fill:#ffebee
326
+ style D fill:#fff3e0
327
+ style H fill:#fff9c4
328
+ ```
329
+
330
+ ```ruby
331
+ begin
332
+ pet = client.get_pet(999999)
333
+ rescue PetstoreApiClient::NotFoundError => e
334
+ puts "Not found: #{e.message}"
335
+ rescue PetstoreApiClient::AuthenticationError => e
336
+ puts "Auth failed: #{e.message}"
337
+ rescue PetstoreApiClient::ValidationError => e
338
+ puts "Validation: #{e.message}"
339
+ rescue PetstoreApiClient::ApiError => e
340
+ puts "API error: #{e.message} (#{e.status_code})"
341
+ end
342
+ ```
343
+
344
+ ## ๐Ÿ›๏ธ Architecture
345
+
346
+ ```mermaid
347
+ graph TB
348
+ A[Your App] --> B[ApiClient]
349
+ B --> C[PetClient]
350
+ B --> D[StoreClient]
351
+
352
+ C --> E[Request Module]
353
+ D --> E
354
+
355
+ E --> F[Connection]
356
+ F --> G[Middleware Stack]
357
+
358
+ G --> H[AuthMiddleware<br/>๐Ÿ” Add auth headers]
359
+ H --> I[RetryMiddleware<br/>๐Ÿ”„ Auto-retry]
360
+ I --> J[RateLimitMiddleware<br/>โฑ๏ธ Handle 429]
361
+ J --> K[JSON Parser]
362
+ K --> L[Petstore API]
363
+
364
+ M[Configuration] -.-> B
365
+ M -.-> F
366
+
367
+ N[Authentication<br/>Strategy] --> O[ApiKey]
368
+ N --> P[OAuth2]
369
+ N --> Q[Composite]
370
+ N --> R[None]
371
+
372
+ H -.uses.-> N
373
+
374
+ style B fill:#e1f5ff
375
+ style C fill:#fff3e0
376
+ style D fill:#fff3e0
377
+ style H fill:#c8e6c9
378
+ style I fill:#fff9c4
379
+ style J fill:#ffcdd2
380
+ ```
381
+
382
+ ## ๐Ÿงช Testing
383
+
384
+ | Metric | Value |
385
+ |------------------------|-------------|
386
+ | โœ… **Total Tests** | 454 passing |
387
+ | ๐Ÿ“Š **Line Coverage** | 96.91% |
388
+ | ๐Ÿ”€ **Branch Coverage** | 86.21% |
389
+ | ๐ŸŽฏ **RuboCop** | 0 offenses |
390
+
391
+ ### ๐Ÿš€ Quick Test (From Project Root)
392
+
393
+ ```bash
394
+ # One-command test
395
+ ./bin/test
396
+
397
+ # Or manually
398
+ bundle install
399
+ bundle exec rspec
400
+
401
+ # With detailed output
402
+ bundle exec rspec --format documentation
403
+
404
+ # Lint check
405
+ bundle exec rubocop
406
+ ```
407
+
408
+ ### ๐Ÿ“Š Coverage Report
409
+
410
+ ```bash
411
+ bundle exec rspec
412
+ open coverage/index.html # Mac
413
+ xdg-open coverage/index.html # Linux
414
+ ```
415
+
416
+ ### ๐ŸŽฎ Interactive Console
417
+
418
+ **IRB Console (Pre-configured):**
419
+ ```bash
420
+ bin/console
421
+ ```
422
+
423
+ The console automatically loads the gem and creates a `client` instance:
424
+
425
+ ```ruby
426
+ # Client is ready to use!
427
+ pet = client.create_pet(
428
+ name: "TestDog",
429
+ photo_urls: ["http://example.com/dog.jpg"],
430
+ status: "available"
431
+ )
432
+ puts "Created: #{pet.name} (ID: #{pet.id})"
433
+
434
+ # Test OAuth2 authentication
435
+ client.configure do |config|
436
+ config.auth_strategy = :oauth2
437
+ config.oauth2_client_id = "test-client"
438
+ config.oauth2_client_secret = "test-secret"
439
+ end
440
+
441
+ # Clean up
442
+ client.delete_pet(pet.id)
443
+ ```
444
+
445
+ ### ๐Ÿš‚ Rails Console Integration
446
+
447
+ **Option 1: Gemfile Installation**
448
+
449
+ Add to your Rails `Gemfile`:
450
+ ```ruby
451
+ gem 'petstore_api_client'
452
+ ```
453
+
454
+ Then in Rails console:
455
+ ```ruby
456
+ rails console
457
+ ```
458
+
459
+ ```ruby
460
+ # Create client with API Key
461
+ client = PetstoreApiClient::ApiClient.new
462
+ client.configure do |config|
463
+ config.api_key = ENV['PETSTORE_API_KEY']
464
+ # or
465
+ config.api_key = :from_env
466
+ end
467
+
468
+ # Test it
469
+ pet = client.create_pet(
470
+ name: "RailsPet",
471
+ photo_urls: ["https://example.com/rails-pet.jpg"]
472
+ )
473
+ ```
474
+
475
+ **Option 2: Load from Local Path**
476
+
477
+ In Rails console:
478
+ ```ruby
479
+ # Load from local gem directory
480
+ $LOAD_PATH.unshift('/path/to/petstore-api-client/lib')
481
+ require 'petstore_api_client'
482
+
483
+ # Use it
484
+ client = PetstoreApiClient::ApiClient.new
485
+ ```
486
+
487
+ **Option 3: Rails Initializer**
488
+
489
+ Create `config/initializers/petstore.rb`:
490
+ ```ruby
491
+ # config/initializers/petstore.rb
492
+ PetstoreApiClient.configure do |config|
493
+ config.auth_strategy = :oauth2
494
+ config.oauth2_client_id = ENV['PETSTORE_OAUTH2_CLIENT_ID']
495
+ config.oauth2_client_secret = ENV['PETSTORE_OAUTH2_CLIENT_SECRET']
496
+ config.timeout = 60
497
+ end
498
+ ```
499
+
500
+ Then in your Rails app:
501
+ ```ruby
502
+ # app/services/pet_service.rb
503
+ class PetService
504
+ def self.create_pet(name:, photo_urls:)
505
+ client = PetstoreApiClient::ApiClient.new
506
+ client.create_pet(
507
+ name: name,
508
+ photo_urls: photo_urls,
509
+ status: 'available'
510
+ )
511
+ rescue PetstoreApiClient::ValidationError => e
512
+ Rails.logger.error("Validation failed: #{e.message}")
513
+ nil
514
+ end
515
+ end
516
+ ```
517
+
518
+ ### ๐Ÿ” Environment Setup
519
+
520
+ **1. Copy environment template:**
521
+ ```bash
522
+ cp .env.example .env
523
+ ```
524
+
525
+ **2. Edit `.env` with your credentials:**
526
+ ```bash
527
+ # Choose your auth strategy
528
+ PETSTORE_API_KEY=special-key
529
+
530
+ # OR for OAuth2
531
+ PETSTORE_OAUTH2_CLIENT_ID=my-client-id
532
+ PETSTORE_OAUTH2_CLIENT_SECRET=my-secret
533
+ ```
534
+
535
+ **3. Load in Rails:**
536
+ ```ruby
537
+ # Gemfile
538
+ gem 'dotenv-rails', groups: [:development, :test]
539
+
540
+ # .env is automatically loaded
541
+ ```
542
+
543
+ ### โš ๏ธ Security Checklist
544
+
545
+ Before committing:
546
+ ```bash
547
+ # 1. Check .gitignore includes sensitive files
548
+ cat .gitignore | grep -E '\.env|credentials|secrets|\.pem|\.key'
549
+
550
+ # 2. Verify no secrets in git
551
+ git status
552
+ git diff
553
+
554
+ # 3. Check for hardcoded secrets
555
+ grep -r "client_secret\|api_key" lib/ --exclude-dir=spec
556
+
557
+ # 4. Ensure .env is not staged
558
+ git ls-files | grep "\.env$" && echo "โš ๏ธ WARNING: .env is tracked!"
559
+ ```
560
+
561
+ **Never commit:**
562
+ - โŒ `.env` files
563
+ - โŒ `credentials.json`
564
+ - โŒ `*.pem`, `*.key` files
565
+ - โŒ OAuth2 client secrets
566
+ - โŒ API keys in code
567
+
568
+ ### ๐Ÿ”„ CI/CD Pipeline
569
+
570
+ GitHub Actions automatically runs on push/PR:
571
+
572
+ | Step | Command | Purpose |
573
+ |-------------|-----------------------|----------------------------|
574
+ | ๐Ÿงช Tests | `bundle exec rspec` | Run 454 tests |
575
+ | ๐Ÿ” Lint | `bundle exec rubocop` | Code quality |
576
+ | ๐Ÿ”’ Security | `bundle audit` | Dependency vulnerabilities |
577
+ | ๐Ÿ“ฆ Build | `gem build` | Build gem package |
578
+ | ๐Ÿ“Š Coverage | Check 95%+ threshold | Ensure quality |
579
+
580
+ **View CI status:**
581
+ ```
582
+ https://github.com/hammadxcm/petstore-api-client/actions
583
+ ```
584
+
585
+ **CI/CD Badge:**
586
+ ```markdown
587
+ [![CI](https://github.com/hammadxcm/petstore-api-client/workflows/CI/badge.svg)](https://github.com/hammadxcm/petstore-api-client/actions)
588
+ ```
589
+
590
+ ## ๐Ÿ“‹ API Coverage
591
+
592
+ | Endpoint | Method | Client Method |
593
+ |---------------------|--------|--------------------------------|
594
+ | `/pet` | POST | `create_pet(data)` |
595
+ | `/pet` | PUT | `update_pet(data)` |
596
+ | `/pet/{id}` | GET | `get_pet(id)` |
597
+ | `/pet/{id}` | DELETE | `delete_pet(id)` |
598
+ | `/pet/findByStatus` | GET | `find_by_status(status, opts)` |
599
+ | `/pet/findByTags` | GET | `find_by_tags(tags, opts)` |
600
+ | `/store/order` | POST | `create_order(data)` |
601
+ | `/store/order/{id}` | GET | `get_order(id)` |
602
+ | `/store/order/{id}` | DELETE | `delete_order(id)` |
603
+
604
+ ## ๐Ÿ“– Documentation
605
+
606
+ - ๐Ÿ”ง [YARD Docs](https://rubydoc.info/gems/petstore_api_client) - Full API reference
607
+ - ๐Ÿ“˜ Authentication guide is included above (see Authentication section)
608
+ - ๐Ÿšฉ Feature flags documented above (see Auth Strategies)
609
+
610
+ ## ๐Ÿ—๏ธ Design Principles
611
+
612
+ โœ… **SOLID** - Single Responsibility, Open/Closed, Liskov, Interface Segregation, Dependency Inversion
613
+ โœ… **Strategy Pattern** - Swappable authentication strategies
614
+ โœ… **Middleware Pattern** - Composable Faraday middleware
615
+ โœ… **Factory Pattern** - Configuration builds authenticators
616
+ โœ… **Composite Pattern** - Combine multiple auth strategies
617
+ โœ… **Null Object** - None authenticator for consistent interface
618
+
619
+ ## ๐Ÿ“ฆ Dependencies
620
+
621
+ **Runtime:**
622
+ - `faraday` (~> 2.0) - HTTP client
623
+ - `faraday-retry` (~> 2.0) - Auto-retry middleware
624
+ - `oauth2` (~> 2.0) - OAuth2 client
625
+ - `activemodel` (>= 6.0) - Validations
626
+
627
+ **Development:**
628
+ - `rspec` (~> 3.12) - Testing
629
+ - `vcr` (~> 6.0) - HTTP recording
630
+ - `simplecov` (~> 0.22) - Coverage
631
+
632
+ ## ๐Ÿค Contributing
633
+
634
+ Contributions are welcome! Please feel free to submit a Pull Request.
635
+
636
+ **How to contribute:**
637
+
638
+ 1. ๐Ÿด Fork it ([https://github.com/hammadxcm/petstore-api-client/fork](https://github.com/hammadxcm/petstore-api-client/fork))
639
+ 2. ๐ŸŒฟ Create feature branch (`git checkout -b feature/amazing-feature`)
640
+ 3. โœ… Add tests for your changes
641
+ 4. ๐Ÿงช Run tests (`bundle exec rspec`)
642
+ 5. ๐Ÿ” Run linter (`bundle exec rubocop`)
643
+ 6. ๐Ÿ’พ Commit (`git commit -m 'Add amazing feature'`)
644
+ 7. ๐Ÿ“ค Push (`git push origin feature/amazing-feature`)
645
+ 8. ๐ŸŽ‰ Create Pull Request
646
+
647
+ **Code owners:** Changes will be automatically reviewed by [@hammadxcm](https://github.com/hammadxcm)
648
+
649
+ **Guidelines:**
650
+ - Write tests for new features
651
+ - Follow existing code style
652
+ - Update documentation
653
+ - Keep commits focused and atomic
654
+
655
+ ## ๐Ÿ“„ License
656
+
657
+ MIT License - see [LICENSE](LICENSE)
658
+
659
+ ---
660
+
661
+ ## ๐Ÿ’ฌ Support & Contact
662
+
663
+ - ๐Ÿ‘ค **Author:** Hammad Khan ([@hammadxcm](https://github.com/hammadxcm))
664
+ - ๐Ÿ› **Issues:** [GitHub Issues](https://github.com/hammadxcm/petstore-api-client/issues)
665
+ - ๐Ÿ’ก **Feature Requests:** [GitHub Discussions](https://github.com/hammadxcm/petstore-api-client/discussions)
666
+ - ๐Ÿ“ง **Contact:** [Open an issue](https://github.com/hammadxcm/petstore-api-client/issues/new)
667
+ - โญ **Star the repo:** [github.com/hammadxcm/petstore-api-client](https://github.com/hammadxcm/petstore-api-client)
668
+
669
+ ---
670
+
671
+ <div align="center">
672
+
673
+ **๐Ÿพ Made with โค๏ธ for the Ruby community by [@hammadxcm](https://github.com/hammadxcm)**
674
+
675
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-ruby.svg)](https://www.ruby-lang.org/)
676
+ [![OAuth2](https://img.shields.io/badge/OAuth2-supported-success.svg)](https://oauth.net/2/)
677
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
678
+ [![GitHub](https://img.shields.io/badge/GitHub-hammadxcm-181717.svg?logo=github)](https://github.com/hammadxcm)
679
+
680
+ [Quick Start](#-quick-start) โ€ข [Authentication](#-authentication) โ€ข [Examples](#-usage-examples) โ€ข [Contributing](#-contributing) โ€ข [Issues](https://github.com/hammadxcm/petstore-api-client/issues)
681
+
682
+ **Repository:** [github.com/hammadxcm/petstore-api-client](https://github.com/hammadxcm/petstore-api-client)
683
+
684
+ </div>
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]